11 #include <type_traits> 20 const char kDigit[2][32] = {
"0123456789abcdef",
"0123456789ABCDEF" };
23 void ReducePadding(
string_view s,
size_t *capacity) {
28 void ReducePadding(
size_t n,
size_t *capacity) {
29 *capacity =
Excess(n, *capacity);
33 struct MakeUnsigned : std::make_unsigned<T> {};
35 struct MakeUnsigned<absl::
uint128> {
40 struct IsSigned : std::is_signed<T> {};
42 struct IsSigned<absl::
uint128> : std::false_type {};
44 class ConvertedIntInfo {
48 using Unsigned =
typename MakeUnsigned<T>::type;
49 auto u =
static_cast<Unsigned
>(
v);
56 UnsignedToStringRight(u, conv);
62 bool is_neg()
const {
return is_neg_; }
65 template <
typename T,
bool IsSigned>
67 static bool Eval(T v) {
return v < 0; }
70 struct IsNegImpl<T, false> {
84 switch (conv.
radix()) {
88 *--p = static_cast<char>(
'0' + static_cast<size_t>(u % 10));
92 *--p = static_cast<char>(
'0' + static_cast<size_t>(u % 8));
95 const char *digits = kDigit[conv.
upper() ? 1 : 0];
96 for (; u; u /= 16) *--p = digits[static_cast<size_t>(u % 16)];
100 size_ =
static_cast<int>(
end() - p);
114 string_view BaseIndicator(
const ConvertedIntInfo &info,
115 const ConversionSpec conv) {
116 bool alt = conv.flags().alt;
117 int radix = conv.conv().radix();
123 if (alt && radix == 16 && !info.digits().empty()) {
124 if (conv.conv().upper())
return "0X";
130 string_view SignColumn(
bool neg,
const ConversionSpec conv) {
131 if (conv.conv().is_signed()) {
133 if (conv.flags().show_pos)
return "+";
134 if (conv.flags().sign_col)
return " ";
139 bool ConvertCharImpl(
unsigned char v,
const ConversionSpec conv,
140 FormatSinkImpl *sink) {
142 if (conv.width() >= 0) fill = conv.width();
143 ReducePadding(1, &fill);
144 if (!conv.flags().left) sink->Append(fill,
' ');
146 if (conv.flags().left) sink->Append(fill,
' ');
150 bool ConvertIntImplInner(
const ConvertedIntInfo &info,
151 const ConversionSpec conv, FormatSinkImpl *sink) {
155 if (conv.width() >= 0) fill = conv.width();
157 string_view formatted = info.digits();
158 ReducePadding(formatted, &fill);
160 string_view sign = SignColumn(info.is_neg(), conv);
161 ReducePadding(sign, &fill);
163 string_view base_indicator = BaseIndicator(info, conv);
164 ReducePadding(base_indicator, &fill);
166 int precision = conv.precision();
167 bool precision_specified = precision >= 0;
168 if (!precision_specified)
175 if (formatted.empty() || *formatted.begin() !=
'0') {
176 int needed =
static_cast<int>(formatted.size()) + 1;
177 precision = std::max(precision, needed);
181 size_t num_zeroes =
Excess(formatted.size(), precision);
182 ReducePadding(num_zeroes, &fill);
184 size_t num_left_spaces = !conv.flags().left ? fill : 0;
185 size_t num_right_spaces = conv.flags().left ? fill : 0;
190 if (!precision_specified && conv.flags().zero) {
191 num_zeroes += num_left_spaces;
195 sink->Append(num_left_spaces,
' ');
197 sink->Append(base_indicator);
198 sink->Append(num_zeroes,
'0');
199 sink->Append(formatted);
200 sink->Append(num_right_spaces,
' ');
204 template <
typename T>
205 bool ConvertIntImplInner(T v,
const ConversionSpec conv, FormatSinkImpl *sink) {
206 ConvertedIntInfo info(v, conv.conv());
208 if (info.is_neg()) sink->Append(1,
'-');
209 if (info.digits().empty()) {
210 sink->Append(1,
'0');
212 sink->Append(info.digits());
216 return ConvertIntImplInner(info, conv, sink);
219 template <
typename T>
220 bool ConvertIntArg(T v,
const ConversionSpec conv, FormatSinkImpl *sink) {
221 if (conv.conv().is_float()) {
225 return ConvertCharImpl(static_cast<unsigned char>(v), conv, sink);
226 if (!conv.conv().is_integral())
229 using U =
typename MakeUnsigned<T>::type;
232 return ConvertIntImplInner(v, conv, sink);
235 template <
typename T>
236 bool ConvertFloatArg(T v,
const ConversionSpec conv, FormatSinkImpl *sink) {
240 inline bool ConvertStringArg(string_view v,
const ConversionSpec conv,
241 FormatSinkImpl *sink) {
244 if (conv.flags().basic) {
248 return sink->PutPaddedString(v, conv.width(), conv.precision(),
258 return {ConvertStringArg(v, conv, sink)};
264 return {ConvertStringArg(v, conv, sink)};
276 len = std::strlen(v);
279 len = std::find(v, v + conv.
precision(),
'\0') - v;
281 return {ConvertStringArg(
string_view(v, len), conv, sink)};
293 return {ConvertIntImplInner(v.
value, conv, sink)};
299 return {ConvertFloatArg(v, conv, sink)};
303 return {ConvertFloatArg(v, conv, sink)};
308 return {ConvertFloatArg(v, conv, sink)};
314 return {ConvertIntArg(v, conv, sink)};
319 return {ConvertIntArg(v, conv, sink)};
324 return {ConvertIntArg(v, conv, sink)};
331 return {ConvertIntArg(v, conv, sink)};
336 return {ConvertIntArg(v, conv, sink)};
340 return {ConvertIntArg(v, conv, sink)};
344 return {ConvertIntArg(v, conv, sink)};
349 return {ConvertIntArg(v, conv, sink)};
354 return {ConvertIntArg(v, conv, sink)};
359 return {ConvertIntArg(v, conv, sink)};
364 return {ConvertIntArg(v, conv, sink)};
369 return {ConvertIntArg(v, conv, sink)};
std::pair< uint64_t, uint64_t > uint128
constexpr size_type size() const noexcept