36constexpr const uint64_t pow10_0to19[]=
56 1000000000000000000UL,
57 10000000000000000000UL,
61constexpr const uint8_t binSizeToDecSize[]
63 20, 19, 19, 19, 19, 18, 18, 18, 17, 17, 17, 16, 16, 16, 16, 15,
64 15, 15, 14, 14, 14, 13, 13, 13, 13, 12, 12, 12, 11, 11, 11, 10,
65 10, 10, 10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6,
66 05, 5, 5, 4, 4, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1
70{
return ((
int(lhs) &
int(rhs)) != 0); }
76template<
typename TChar>
83 if( idx < 0 || idx >= length )
86 const TChar* buf= src.
Buffer();
89 while ( idx < length )
91 const TChar c= buf[idx];
92 if ( c <
'0' || c >
'9' )
95 result= ( result * 10 ) + uint64_t( c -
'0' );
107template<
typename TChar>
113 if ( startIdx < 0 || startIdx >= srcLength )
117 const TChar* buffer= src.
Buffer();
119 integer idx= src.
template IndexOfAny<lang::Inclusion::Exclude, NC>( nf.
Whitespaces, startIdx );
125 if ( (negative= (buffer[idx] ==
'-')) ==
true || buffer[idx] ==
'+' )
127 if( (idx= src.
template IndexOfAny<lang::Inclusion::Exclude, NC>( nf.
Whitespaces, idx + 1 ) ) == -1 )
138 && ( idx + prefixLen < srcLength )
140 && nf.
Whitespaces.IndexOf( buffer[ idx + prefixLen ] ) == -1 )
143 result= int64_t(
ParseHex( src, idx, nf ) );
144 if( idx - prefixLen == oldIdx )
150 && ( idx + prefixLen < srcLength )
152 && nf.
Whitespaces.IndexOf( buffer[ idx + prefixLen ] ) == -1 )
155 result= int64_t(
ParseBin( src, idx, nf ) );
156 if( idx - prefixLen == oldIdx )
162 && ( idx + prefixLen < srcLength )
164 && nf.
Whitespaces.IndexOf( buffer[ idx + prefixLen ] ) == -1 )
167 result= int64_t(
ParseOct( src, idx, nf ) );
168 if( idx - prefixLen == oldIdx )
175 result= int64_t(
ParseDec( src, idx, nf ) );
183 return negative ? int64_t(-result)
189template<
typename TChar>
195 integer idx= src.
template IndexOfAny<lang::Inclusion::Exclude>( nf.
Whitespaces, startIdx );
200 bool charFound=
false;
202 const TChar* buf= src.
Buffer();
203 while ( idx < length )
205 const TChar c= buf[idx];
207 && hasBits(nf.
Flags, NumberFormatFlags::ReadGroupChars)
215 if ( c <
'0' || c >
'9' )
219 result= ( result * 10 ) + uint64_t( c -
'0' );
230template<
typename TChar>
236 integer idx= src.
template IndexOfAny<lang::Inclusion::Exclude>( nf.
Whitespaces, startIdx );
241 bool charFound=
false;
243 const TChar* buf = src.
Buffer();
244 while ( idx < length )
248 && hasBits(nf.
Flags, NumberFormatFlags::ReadGroupChars)
284template<
typename TChar>
290 integer idx= src.
template IndexOfAny<lang::Inclusion::Exclude>( nf.
Whitespaces, startIdx );
295 bool charFound=
false;
297 const TChar* buf= src.
Buffer();
298 while ( idx < length )
302 && hasBits(nf.
Flags, NumberFormatFlags::ReadGroupChars)
312 if ( c >=
'0' && c <=
'9' )
315 result|= uint64_t(c -
'0');
321 if ( c >=
'A' && c <=
'F' )
324 result|= uint64_t(c -
'A' + 10 );
330 if ( c >=
'a' && c <=
'f' )
333 result|= uint64_t(c -
'a' + 10 );
348template<
typename TChar>
354 integer idx= src.
template IndexOfAny<lang::Inclusion::Exclude>( nf.
Whitespaces, startIdx );
359 bool charFound=
false;
361 const TChar* buf= src.
Buffer();
362 while ( idx < length )
366 && hasBits(nf.
Flags, NumberFormatFlags::ReadGroupChars)
374 if ( c >=
'0' && c <=
'7' )
377 result|= uint64_t(c -
'0');
391template<
typename TChar>
395 if( startIdx < 0 || startIdx >= src.
Length() )
399 const TChar* buf= src.
Buffer() + startIdx;
404 integer skip= src.
template IndexOfAny<lang::Inclusion::Exclude>( nf.
Whitespaces, startIdx );
407 buf+= skip - startIdx;
411 bool negative= (*buf ==
'-');
412 if ( negative || *buf ==
'+' )
414 if( ++buf == bufEnd )
424 if( buf + nf.
NANLiteral.Length() - 1 <= bufEnd
428 return std::numeric_limits<double>::quiet_NaN();
431 if( buf + nf.
INFLiteral.Length() - 1 <= bufEnd
435 return negative ? -std::numeric_limits<double>::infinity()
436 : std::numeric_limits<double>::infinity();
443 bool integralPartFound= isdigit(
int(c));
444 if ( integralPartFound )
446 if ( c <
'0' || c >
'9' )
456 ALIB_ASSERT_ERROR( buf <= bufEnd,
"STRINGS",
"Error in float parsing algorithm." )
459 startIdx= buf - src.
Buffer();
460 return negative ? -result : result;
471 && *buf >=
'0' && *buf <=
'9' )
476 result+= ( intValue / pow( 10,
double(intIdx) ) );
479 else if( !integralPartFound )
486 bool eSepFound=
false;
488 if ( buf + sepLen < bufEnd )
494 if ( (eSepFound= ( pos == sepLen ) ) ==
true )
497 if ( !eSepFound && ( *buf ==
'e' || *buf ==
'E' ) )
504 if (eSepFound && buf < bufEnd)
506 bool negativeE=
false;
507 if ( (negativeE= (*buf ==
'-') ) ==
true || *buf ==
'+' )
517 result*= pow( 10, negativeE ? -exp : exp );
529 startIdx= buf - src.
Buffer();
532 return negative ? -result : result;
535template<
typename TChar>
539 int width= overrideWidth != 0 ? overrideWidth
542 if ( width < 1 ) width= 1;
551 int leadingBinaryZeros=
lang::CLZ(value);
552 digitsInValue= binSizeToDecSize[leadingBinaryZeros];
555 if( value < pow10_0to19[digitsInValue-1] )
559 && (digitsInValue == 20 || value < pow10_0to19[digitsInValue ]),
560 "STRINGS",
"Error calculating the number of digits in value {}",
574 requestedDigits= width - width / 4;
580 requestedDigits= width;
583 printDigits= (std::max)( requestedDigits, digitsInValue );
588 "STRINGS",
"Internal error, false assumption" )
589 if( printDigits >1 && width > printDigits + (printDigits - 1) / 3 )
594 bool printSpace= hasBits(nf.
Flags, NumberFormatFlags::ReplaceLeadingZerosWithSpaces);
595 int actDigit= printDigits;
596 while ( actDigit > 0 )
599 int digitValue= int( ( value / pow10_0to19[actDigit-1] ) );
604 && actDigit != printDigits
610 printSpace&= (digitValue == 0 && actDigit > 1);
611 buffer[idx++]= printSpace ? TChar(
' ') : TChar( 48 + digitValue );
614 value= value % pow10_0to19[actDigit-1];
622template<
typename TChar>
632 uValue= uint64_t( value );
638 uValue= uint64_t( -value );
642 int width= overrideWidth != 0 ? overrideWidth
644 if( idx != oldIdx && width > 1 )
651template<
typename TChar>
656 int groupWidth= !hasBits(nf.
Flags, NumberFormatFlags::WriteGroupChars) ? 0
664 int nextSeparator= 0;
667 int digits= overrideWidth != 0 ? overrideWidth : nf.
BinFieldWidth;
670 if ( groupWidth != 0 )
672 nextSeparator= digits<= groupWidth ? 0
673 : ( digits >= groupWidth
674 && (digits % (groupWidth + 1)) == 0 ) ? 1 : 2;
676 digits-= digits / (groupWidth + 1);
689 uint64_t testValue= uint64_t(1) << (digits - 1);
693 if( groupWidth != 0 && ( digits % groupWidth) == 0 )
695 if ( nextSeparator != 0 )
704 buffer[idx++]= ( value & testValue ) == 0L ?
'0' :
'1';
714template<
typename TChar>
719 int groupWidth= !hasBits(nf.
Flags, NumberFormatFlags::WriteGroupChars) ? 0
726 int nextSeparator= 0;
728 int digits= overrideWidth != 0 ? overrideWidth : nf.
HexFieldWidth;
733 if ( groupWidth != 0 )
735 nextSeparator= digits<= groupWidth ? 0
736 : ( digits >= groupWidth
737 && (digits % (groupWidth + 1)) == 0 ) ? 1 : 2;
739 digits-= digits / (groupWidth + 1);
745 digits= value != 0 ? (
lang::MSB(value)-1) / 4 + 1
752 unsigned int characterA=
static_cast<unsigned int>( hasBits(nf.
Flags, NumberFormatFlags::HexLowerCase) ?
'a' :
'A' );
753 int shiftBits= (digits -1 ) * 4;
754 uint64_t testMask= uint64_t( 15 ) << shiftBits;
758 if( groupWidth != 0 && ( digits % groupWidth) == 0 )
760 if ( nextSeparator != 0 )
768 unsigned int nibble=
static_cast<unsigned int>( ( value & testMask ) >> shiftBits );
769 buffer[idx++]= ( nibble < 10 ) ? static_cast<TChar>(
'0' + nibble)
770 :
static_cast<TChar
>(characterA + (nibble - 10));
781template<
typename TChar>
786 const int groupWidth= hasBits(nf.
Flags, NumberFormatFlags::WriteGroupChars) && nf.
OctGroupChar !=
'\0' ? 3 : 0;
790 int nextSeparator= 0;
793 int digits= overrideWidth != 0 ? overrideWidth : nf.
OctFieldWidth;
796 if ( groupWidth != 0 )
798 nextSeparator= digits<= groupWidth ? 0
799 : ( digits >= groupWidth
800 && (digits % (groupWidth + 1)) == 0 ) ? 1 : 2;
802 digits-= digits / (groupWidth + 1);
808 digits= value != 0 ? (
lang::MSB(value)-1) / 3 + 1
815 int shiftBits= (digits -1 ) * 3;
819 if( groupWidth != 0 && ( digits % groupWidth) == 0 )
821 if ( nextSeparator != 0 )
827 auto octet= ( value & (uint64_t(7) << shiftBits) ) >> shiftBits;
828 buffer[idx++]=
static_cast<TChar
>(
'0' + octet);
838template<
typename TChar>
846 auto classification= std::fpclassify(value);
847 if( classification == FP_NAN ) {
return idx+= nf.
NANLiteral.CopyTo(buffer + idx); }
848 bool isNegative= std::signbit(value);
851 if( classification == FP_ZERO )
861 if( classification == FP_INFINITE )
867 return idx+= nf.
INFLiteral.CopyTo(buffer + idx);
871 constexpr int MaxFloatSignificantDigits= 16;
875 int exp10= value != 0.0 ? int( floor(log10( value ) ) )
879 bool scientific= ( hasBits(nf.
Flags, NumberFormatFlags::ForceScientific)
881 || ( integralWidth > 0 && exp10 != 0 && exp10 >= (MaxFloatSignificantDigits - integralWidth - 1 ) )
885 integralWidth= (std::min) ( integralWidth, 15 );
893 int unusedFractDigits;
899 auto dotPos= MaxFloatSignificantDigits - exp10;
900 intPart= uint64_t(llrint( value * pow( 10, dotPos ) ));
901 fractPart= intPart % pow10_0to19[ MaxFloatSignificantDigits ];
902 intPart= intPart / pow10_0to19[ MaxFloatSignificantDigits ];
908 ALIB_ASSERT( MaxFloatSignificantDigits - firstNonZero < 20,
"STRINGS")
909 while ( fractPart < pow10_0to19[ MaxFloatSignificantDigits - firstNonZero - 1 ] )
911 ALIB_ASSERT( MaxFloatSignificantDigits - firstNonZero > 0,
"STRINGS")
915 unusedFractDigits= fractionalDigits >= 0 ? MaxFloatSignificantDigits - fractionalDigits
920 else if (exp10 >= 0 )
922 int intPartSize= MaxFloatSignificantDigits - exp10;
923 ALIB_ASSERT( intPartSize > 0 && intPartSize <= MaxFloatSignificantDigits,
"STRINGS" )
924 intPart= uint64_t(llrint( value * pow( 10, intPartSize ) ));
925 fractPart= intPart % pow10_0to19[ intPartSize ];
926 intPart= intPart / pow10_0to19[ intPartSize ];
932 while ( fractPart < pow10_0to19[ intPartSize - firstNonZero - 1 ] )
934 ALIB_ASSERT( intPartSize - firstNonZero > 0,
"STRINGS" )
938 unusedFractDigits= fractionalDigits >= 0 ? intPartSize - fractionalDigits
946 firstNonZero= -exp10;
948 fractPart= uint64_t(llrint( value * pow( 10, MaxFloatSignificantDigits + firstNonZero) ));
949 unusedFractDigits= fractionalDigits >= 0 ? MaxFloatSignificantDigits - ( fractionalDigits - firstNonZero )
954 if ( (fractionalDigits < 0 || fractionalDigits >= firstNonZero - 1 )
955 && unusedFractDigits > 0
956 && unusedFractDigits <= 18 )
959 uint64_t rest= fractPart % pow10_0to19[ unusedFractDigits ];
960 fractPart = fractPart / pow10_0to19[ unusedFractDigits ];
961 if ( rest > pow10_0to19[ unusedFractDigits ] / 2 )
964 int overflowDigit= 0;
965 bool overflow=
false;
966 while ( (overflowDigit <= fractionalDigits || fractionalDigits < 0 )
967 && (overflow|= fractPart == pow10_0to19[ overflowDigit ]) ==
false
968 && fractPart > pow10_0to19[ overflowDigit ]
974 if ( overflowDigit == (fractionalDigits >= 0 ? fractionalDigits : 15) )
993 && ( fractionalDigits < 0 || fractionalDigits > firstNonZero -1)
1001 if ( intPart != 0L || integralWidth != 0 )
1005 if ( fractionalDigits != 0 || hasBits(nf.
Flags, NumberFormatFlags::ForceDecimalPoint) )
1009 if (fractionalDigits != 0)
1011 int fractZeros= firstNonZero - 1;
1012 if ( fractionalDigits > 0 && fractZeros > fractionalDigits )
1013 fractZeros= fractionalDigits;
1015 for (
int i= 0 ; i < fractZeros ; ++i )
1018 int qtyDigits= fractionalDigits - fractZeros;
1019 int actDigit= MaxFloatSignificantDigits + 1;
1020 int cntOmittedZeros= 0;
1022 bool printStarted=
false;
1023 while ( fractPart > 0
1024 && ( qtyDigits< 0 || cntDigits < qtyDigits )
1030 int digitValue= int( ( fractPart / pow10_0to19[actDigit] ) );
1035 if ( (printStarted|= (digitValue != 0)) ==
false )
1040 if ( digitValue == 0 )
1044 for (
int i= 0; i< cntOmittedZeros ; ++i )
1047 buffer[idx++]=
static_cast<TChar
>( 48 + digitValue );
1051 fractPart= fractPart % pow10_0to19[actDigit];
1055 if (fractionalDigits < 0 )
1059 if ( cntDigits < qtyDigits )
1061 if ( hasBits(nf.
Flags, NumberFormatFlags::OmitTrailingFractionalZeros) )
1063 if( cntDigits == 0 )
1068 for (
int i= 0; i< cntOmittedZeros ; ++i )
1070 cntDigits+= cntOmittedZeros;
1073 for (
int i= cntDigits; i< qtyDigits; ++i )
1088 else if ( hasBits(nf.
Flags, NumberFormatFlags::WriteExponentPlusSign) )
1091 idx=
WriteDecUnsigned( uint64_t(exp10 >= 0 ? exp10 : -exp10), buffer, idx, 2, nf );