summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/cxxformat/formatters.hpp209
1 files changed, 82 insertions, 127 deletions
diff --git a/include/cxxformat/formatters.hpp b/include/cxxformat/formatters.hpp
index 99f9f62..515d0ec 100644
--- a/include/cxxformat/formatters.hpp
+++ b/include/cxxformat/formatters.hpp
@@ -21,21 +21,27 @@ namespace format {
return [](char c) constexpr noexcept { return std::string_view{what}.find(c) != std::string_view::npos; };
}
- constexpr void formatPadded(const format_output auto& out, std::string_view subject, char padding, bool leftJustified, optional_int<std::size_t> minWidth)
+ template<typename Outputter>
+ constexpr void formatPadded(const format_output auto& out, Outputter&& outputter, std::size_t outputWidth, char padding, bool leftJustified, optional_int<std::size_t> minWidth)
{
- if(subject.length() < minWidth.value_or(0) && !leftJustified)
+ if(outputWidth < minWidth.value_or(0) && !leftJustified)
{
- out(padding, *minWidth - subject.length());
+ out(padding, *minWidth - outputWidth);
}
- out(subject);
+ outputter(out);
- if(subject.length() < minWidth.value_or(0) && leftJustified)
+ if(outputWidth < minWidth.value_or(0) && leftJustified)
{
- out(padding, *minWidth - subject.length());
+ out(padding, *minWidth - outputWidth);
}
}
+ constexpr void formatPadded(const format_output auto& out, std::string_view subject, char padding, bool leftJustified, optional_int<std::size_t> minWidth)
+ {
+ formatPadded(out, [subject](const auto& out){ out(subject); }, subject.size(), padding, leftJustified, minWidth);
+ }
+
constexpr void formatQuoteGrouped(const format_output auto& out, std::string_view subject, std::size_t leadingZeros, unsigned int grouping)
{
const auto quote = '\'';
@@ -225,8 +231,9 @@ namespace format {
prefix = {&signPrefix, 1};
}
+ const auto numSize = converted.size();
std::size_t precisionPadding{0};
- std::size_t normalPadding{0};
+ const auto restSize = prefix.size();
if (precision)
{
if (*precision > converted.size())
@@ -236,8 +243,6 @@ namespace format {
}
else if (minWidth && spec.padding == '0')
{
- const auto numSize = converted.size();
- const auto restSize = prefix.size();
const auto totalLength = numSize + restSize + (quoteGrouping != 0 ? numSize / quoteGrouping : 0);
if (*minWidth > totalLength)
{
@@ -254,40 +259,23 @@ namespace format {
}
}
- if (minWidth)
- {
- const auto numSize = converted.size();
- const auto quoteSize = quoteGrouping != 0 ? ((numSize + precisionPadding - 1) / quoteGrouping) : 0;
- const auto totalLength = numSize + precisionPadding + quoteSize + prefix.size();
- if (*minWidth > totalLength)
- {
- normalPadding = *minWidth - totalLength;
- }
- }
-
- const auto padding = precision ? ' ' : spec.padding;
- if(!spec.flags.leftJustified)
- {
- out(padding, normalPadding);
- }
+ const auto quoteSize = quoteGrouping != 0 ? ((numSize + precisionPadding - 1) / quoteGrouping) : 0;
+ const auto totalLength = numSize + precisionPadding + quoteSize + restSize;
- out(prefix);
-
- if (quoteGrouping != 0)
- {
- formatQuoteGrouped(out, converted, precisionPadding, quoteGrouping);
- }
- else
+ formatPadded(out, [prefix, converted, precisionPadding, quoteGrouping](const auto& out)
{
- out('0', precisionPadding);
- out(converted);
- }
+ out(prefix);
- if(spec.flags.leftJustified)
- {
- out(padding, normalPadding);
- }
- return;
+ if (quoteGrouping != 0)
+ {
+ formatQuoteGrouped(out, converted, precisionPadding, quoteGrouping);
+ }
+ else
+ {
+ out('0', precisionPadding);
+ out(converted);
+ }
+ }, totalLength, precision ? ' ' : spec.padding, spec.flags.leftJustified, minWidth);
}
static constexpr void conversionSupported(format_specifier spec)
@@ -507,67 +495,55 @@ namespace format {
}
}
-
- std::size_t zeroPadding = 0;
- std::size_t paddingLength{0};
- if (minWidth)
+ std::size_t zeroPadding{0};
+ const auto prefixSize = (signPrefix != '\0' ? 1 : 0) + hexPrefix.size();
+ const auto dotSize = (addDot ? 1 : 0);
+ const auto integralDigitCount = integralPart.size();
+ const auto convertedSize = converted.size();
+ std::size_t totalLength{prefixSize + convertedSize + dotSize + extraZeros + (quoteGrouping != 0 ? integralDigitCount / quoteGrouping : 0)};
+ if (minWidth && *minWidth > totalLength)
{
- const auto prefixSize = (signPrefix != '\0' ? 1 : 0) + hexPrefix.size();
- const auto dotSize = (addDot ? 1 : 0);
- const auto integralDigitCount = integralPart.size();
- const auto convertedSize = converted.size();
- const auto totalLength = prefixSize + convertedSize + dotSize + extraZeros + (quoteGrouping != 0 ? integralDigitCount / quoteGrouping : 0);
- if (*minWidth > totalLength)
+ if (quoteGrouping != 0 && spec.padding == '0')
{
- if (quoteGrouping != 0 && spec.padding == '0')
- {
- zeroPadding = calculateNeededGroupedZeroPadding(*minWidth - prefixSize - dotSize - (convertedSize - integralDigitCount), integralDigitCount, quoteGrouping);
- spec.padding = ' ';
- paddingLength = *minWidth - (totalLength + zeroPadding + zeroPadding / quoteGrouping);
- }
- else
+ zeroPadding = calculateNeededGroupedZeroPadding(*minWidth - prefixSize - dotSize - (convertedSize - integralDigitCount), integralDigitCount, quoteGrouping);
+ spec.padding = ' ';
+ totalLength += zeroPadding + (zeroPadding / quoteGrouping);
+ }
+ else
+ {
+ if(spec.padding == '0')
{
- paddingLength = *minWidth - totalLength;
- if(!spec.flags.leftJustified && spec.padding == '0')
- {
- zeroPadding = paddingLength;
- }
+ zeroPadding = *minWidth - totalLength;
+ totalLength += zeroPadding;
}
}
}
- if(!spec.flags.leftJustified && spec.padding != '0')
+ formatPadded(out, [signPrefix, hexPrefix, quoteGrouping, mantissa, integralPart, fractionalPart, exponent, zeroPadding, extraZeros, addDot](const auto& out)
{
- out(spec.padding, paddingLength);
- }
-
- if (signPrefix != '\0')
- {
- out(signPrefix);
- }
- out(hexPrefix);
-
- if (quoteGrouping != 0)
- {
- formatQuoteGrouped(out, integralPart, zeroPadding, quoteGrouping);
- out(fractionalPart);
- }
- else
- {
- out('0', zeroPadding);
- out(mantissa);
- }
- if (addDot)
- {
- out('.');
- }
- out('0', extraZeros);
- out(exponent);
+ if (signPrefix != '\0')
+ {
+ out(signPrefix);
+ }
+ out(hexPrefix);
- if(spec.flags.leftJustified)
- {
- out(spec.padding, paddingLength);
- }
+ if (quoteGrouping != 0)
+ {
+ formatQuoteGrouped(out, integralPart, zeroPadding, quoteGrouping);
+ out(fractionalPart);
+ }
+ else
+ {
+ out('0', zeroPadding);
+ out(mantissa);
+ }
+ if (addDot)
+ {
+ out('.');
+ }
+ out('0', extraZeros);
+ out(exponent);
+ }, totalLength, ' ', spec.flags.leftJustified, minWidth);
return;
}
@@ -584,47 +560,26 @@ namespace format {
struct formatter<S> {
static constexpr void format(const format_output auto& out, const S& s, format_specifier spec, optional_int<std::size_t> minWidth, optional_int<std::size_t> precision)
{
- std::string_view val{s};
- if (precision)
- {
- val = val.substr(0, *precision);
- }
+ const std::string_view val{precision ? std::string_view{s}.substr(0, *precision) : s};
if (spec.flags.quote)
{
const auto quoteExtra = std::count_if(val.begin(), val.end(), "\"\\"_contains) + 2;
- std::size_t padding = 0;
- if (minWidth)
- {
- const auto totalLength = val.size() + quoteExtra;
- if (*minWidth > totalLength)
+ formatPadded(out, [val](const auto& out){
+ out('"');
+ for (std::size_t pos = 0, startPos = 0; pos < val.size(); )
{
- padding = *minWidth - totalLength;
- }
- }
- if (!spec.flags.leftJustified)
- {
- out(' ', padding);
- }
-
- out('"');
- for (std::size_t pos = 0, startPos = 0; pos < val.size(); )
- {
- pos = val.find_first_of("\"\\", pos);
- out(val.substr(startPos, pos - startPos));
- if (pos != std::string_view::npos)
- {
- out('\\');
- startPos = pos;
- ++pos;
+ pos = val.find_first_of("\"\\", pos);
+ out(val.substr(startPos, pos - startPos));
+ if (pos != std::string_view::npos)
+ {
+ out('\\');
+ startPos = pos;
+ ++pos;
+ }
}
- }
- out('"');
-
- if (spec.flags.leftJustified)
- {
- out(' ', padding);
- }
+ out('"');
+ }, val.size() + quoteExtra, ' ', spec.flags.leftJustified, minWidth);
}
else
{