refactor(strings): refactor zero padding to make it more flexible

This commit is contained in:
Redstone1024 2025-01-14 17:39:19 +08:00
parent 0c6f33762a
commit 23963e0389

View File

@ -1081,10 +1081,10 @@ static_assert(CFormattable<const char[256]>);
* *
* 4. The zero padding part: * 4. The zero padding part:
* *
* This part is allowed only if the type indicator part is not 'C', 'c', 'S' or 's', * This part is allowed only if the type indicator part is not 'C', 'c', 'S' or 's'.
* and the fill and align part is not specified but the width part is specified.
* *
* - '0': Use '0' as the fill character. * - '0': By adding the prefix '0' to satisfy the minimum field width of the object.
* if the object is normal number.
* *
* 5. The width part: * 5. The width part:
* *
@ -1312,7 +1312,7 @@ public:
} }
// Try to parse the zero padding part. // Try to parse the zero padding part.
if (Char == LITERAL(FCharType, '0') && !bHasFillAndAlign) if (Char == LITERAL(FCharType, '0'))
{ {
bZeroPadding = true; bZeroPadding = true;
@ -1681,6 +1681,8 @@ public:
bool bNegative = false; bool bNegative = false;
bool bNormal = false;
size_t TargetWidth; size_t TargetWidth;
const FCharType* Target = nullptr; const FCharType* Target = nullptr;
@ -1728,11 +1730,13 @@ public:
Buffer[0] = Char; Buffer[0] = Char;
Target = Buffer; Target = Buffer.GetData();
break; break;
} }
bNormal = true;
// Handle the illegal base. // Handle the illegal base.
if (!Math::IsWithinInclusive(TargetBase, 2, 36)) if (!Math::IsWithinInclusive(TargetBase, 2, 36))
{ {
@ -1748,7 +1752,7 @@ public:
Buffer[0] = Object ? LITERAL(FCharType, '1') : LITERAL(FCharType, '0'); Buffer[0] = Object ? LITERAL(FCharType, '1') : LITERAL(FCharType, '0');
Target = Buffer; Target = Buffer.GetData();
break; break;
} }
@ -1799,11 +1803,12 @@ public:
} }
while (false); while (false);
size_t ZeroPadding = 0;
size_t LeftPadding = 0; size_t LeftPadding = 0;
size_t RightPadding = 0; size_t RightPadding = 0;
// Estimate the field width. // Estimate the field width.
if (TargetField != 0 && !bZeroPadding) if (TargetField != 0)
{ {
size_t LiteralWidth = TargetWidth; size_t LiteralWidth = TargetWidth;
@ -1829,16 +1834,20 @@ public:
const size_t PaddingWidth = TargetField - Math::Min(LiteralWidth, TargetField); const size_t PaddingWidth = TargetField - Math::Min(LiteralWidth, TargetField);
switch (AlignOption) if (!bZeroPadding || !bNormal)
{ {
case LITERAL(FCharType, '<'): RightPadding = PaddingWidth; break; switch (AlignOption)
case LITERAL(FCharType, '>'): LeftPadding = PaddingWidth; break; {
case LITERAL(FCharType, '^'): case LITERAL(FCharType, '<'): RightPadding = PaddingWidth; break;
LeftPadding = Math::DivAndFloor(PaddingWidth, 2); case LITERAL(FCharType, '>'): LeftPadding = PaddingWidth; break;
RightPadding = PaddingWidth - LeftPadding; case LITERAL(FCharType, '^'):
break; LeftPadding = Math::DivAndFloor(PaddingWidth, 2);
default: check_no_entry(); RightPadding = PaddingWidth - LeftPadding;
break;
default: check_no_entry();
}
} }
else ZeroPadding = PaddingWidth;
} }
// Write the left padding. // Write the left padding.
@ -1896,14 +1905,11 @@ public:
} }
// Handle the zero padding. // Handle the zero padding.
if (bZeroPadding && Target == Buffer.GetData()) for (size_t Index = 0; Index != ZeroPadding; ++Index)
{ {
for (size_t Index = TargetWidth; Index < TargetField; ++Index) if (Iter == Sent) UNLIKELY return Iter;
{
if (Iter == Sent) UNLIKELY return Iter;
*Iter++ = LITERAL(FCharType, '0'); *Iter++ = LITERAL(FCharType, '0');
}
} }
// Write the target object. // Write the target object.
@ -2005,9 +2011,8 @@ static_assert(CFormattable<bool>);
* *
* 4. The zero padding part: * 4. The zero padding part:
* *
* This part is allowed only if the fill and align part is not specified but the width part is specified. * - '0': By adding the prefix '0' to satisfy the minimum field width of the object.
* * if the object is normal number.
* - '0': Use '0' as the fill character.
* *
* 5. The width part: * 5. The width part:
* *
@ -2191,7 +2196,7 @@ public:
} }
// Try to parse the zero padding part. // Try to parse the zero padding part.
if (Char == LITERAL(FCharType, '0') && !bHasFillAndAlign) if (Char == LITERAL(FCharType, '0'))
{ {
bZeroPadding = true; bZeroPadding = true;
@ -2488,6 +2493,8 @@ public:
const bool bNegative = Math::IsNegative(Object); const bool bNegative = Math::IsNegative(Object);
bool bNormal = false;
size_t TargetWidth; size_t TargetWidth;
const char* Target = nullptr; const char* Target = nullptr;
@ -2531,6 +2538,8 @@ public:
// Handle the normal value. // Handle the normal value.
else else
{ {
bNormal = true;
NAMESPACE_STD::to_chars_result ConvertResult; NAMESPACE_STD::to_chars_result ConvertResult;
while (true) while (true)
@ -2557,7 +2566,7 @@ public:
if (ConvertResult.ec != NAMESPACE_STD::errc::value_too_large) break; if (ConvertResult.ec != NAMESPACE_STD::errc::value_too_large) break;
Buffer.Reserve(Buffer.Num() * 2); Buffer.SetNum(Buffer.Num() * 2);
} }
Buffer.SetNum(ConvertResult.ptr - Buffer.GetData()); Buffer.SetNum(ConvertResult.ptr - Buffer.GetData());
@ -2645,11 +2654,12 @@ public:
Target = Buffer.GetData(); Target = Buffer.GetData();
} }
size_t ZeroPadding = 0;
size_t LeftPadding = 0; size_t LeftPadding = 0;
size_t RightPadding = 0; size_t RightPadding = 0;
// Estimate the field width. // Estimate the field width.
if (TargetField != 0 && !bZeroPadding) if (TargetField != 0)
{ {
size_t LiteralWidth = TargetWidth; size_t LiteralWidth = TargetWidth;
@ -2663,16 +2673,20 @@ public:
const size_t PaddingWidth = TargetField - Math::Min(LiteralWidth, TargetField); const size_t PaddingWidth = TargetField - Math::Min(LiteralWidth, TargetField);
switch (AlignOption) if (!bZeroPadding || !bNormal)
{ {
case LITERAL(FCharType, '<'): RightPadding = PaddingWidth; break; switch (AlignOption)
case LITERAL(FCharType, '>'): LeftPadding = PaddingWidth; break; {
case LITERAL(FCharType, '^'): case LITERAL(FCharType, '<'): RightPadding = PaddingWidth; break;
LeftPadding = Math::DivAndFloor(PaddingWidth, 2); case LITERAL(FCharType, '>'): LeftPadding = PaddingWidth; break;
RightPadding = PaddingWidth - LeftPadding; case LITERAL(FCharType, '^'):
break; LeftPadding = Math::DivAndFloor(PaddingWidth, 2);
default: check_no_entry(); RightPadding = PaddingWidth - LeftPadding;
break;
default: check_no_entry();
}
} }
else ZeroPadding = PaddingWidth;
} }
// Write the left padding. // Write the left padding.
@ -2701,14 +2715,11 @@ public:
} }
// Handle the zero padding. // Handle the zero padding.
if (bZeroPadding && Target == Buffer.GetData()) for (size_t Index = 0; Index != ZeroPadding; ++Index)
{ {
for (size_t Index = TargetWidth; Index < TargetField; ++Index) if (Iter == Sent) UNLIKELY return Iter;
{
if (Iter == Sent) UNLIKELY return Iter;
*Iter++ = LITERAL(FCharType, '0'); *Iter++ = LITERAL(FCharType, '0');
}
} }
// Write the target object. // Write the target object.