00001
00002
00003
00004
00005 #include "absl/strings/internal/str_format/arg.h"
00006
00007 #include <cassert>
00008 #include <cerrno>
00009 #include <cstdlib>
00010 #include <string>
00011 #include <type_traits>
00012
00013 #include "absl/base/port.h"
00014 #include "absl/strings/internal/str_format/float_conversion.h"
00015
00016 namespace absl {
00017 namespace str_format_internal {
00018 namespace {
00019
00020 const char kDigit[2][32] = { "0123456789abcdef", "0123456789ABCDEF" };
00021
00022
00023 void ReducePadding(string_view s, size_t *capacity) {
00024 *capacity = Excess(s.size(), *capacity);
00025 }
00026
00027
00028 void ReducePadding(size_t n, size_t *capacity) {
00029 *capacity = Excess(n, *capacity);
00030 }
00031
00032 template <typename T>
00033 struct MakeUnsigned : std::make_unsigned<T> {};
00034 template <>
00035 struct MakeUnsigned<absl::uint128> {
00036 using type = absl::uint128;
00037 };
00038
00039 template <typename T>
00040 struct IsSigned : std::is_signed<T> {};
00041 template <>
00042 struct IsSigned<absl::uint128> : std::false_type {};
00043
00044 class ConvertedIntInfo {
00045 public:
00046 template <typename T>
00047 ConvertedIntInfo(T v, ConversionChar conv) {
00048 using Unsigned = typename MakeUnsigned<T>::type;
00049 auto u = static_cast<Unsigned>(v);
00050 if (IsNeg(v)) {
00051 is_neg_ = true;
00052 u = Unsigned{} - u;
00053 } else {
00054 is_neg_ = false;
00055 }
00056 UnsignedToStringRight(u, conv);
00057 }
00058
00059 string_view digits() const {
00060 return {end() - size_, static_cast<size_t>(size_)};
00061 }
00062 bool is_neg() const { return is_neg_; }
00063
00064 private:
00065 template <typename T, bool IsSigned>
00066 struct IsNegImpl {
00067 static bool Eval(T v) { return v < 0; }
00068 };
00069 template <typename T>
00070 struct IsNegImpl<T, false> {
00071 static bool Eval(T) {
00072 return false;
00073 }
00074 };
00075
00076 template <typename T>
00077 bool IsNeg(T v) {
00078 return IsNegImpl<T, IsSigned<T>::value>::Eval(v);
00079 }
00080
00081 template <typename T>
00082 void UnsignedToStringRight(T u, ConversionChar conv) {
00083 char *p = end();
00084 switch (conv.radix()) {
00085 default:
00086 case 10:
00087 for (; u; u /= 10)
00088 *--p = static_cast<char>('0' + static_cast<size_t>(u % 10));
00089 break;
00090 case 8:
00091 for (; u; u /= 8)
00092 *--p = static_cast<char>('0' + static_cast<size_t>(u % 8));
00093 break;
00094 case 16: {
00095 const char *digits = kDigit[conv.upper() ? 1 : 0];
00096 for (; u; u /= 16) *--p = digits[static_cast<size_t>(u % 16)];
00097 break;
00098 }
00099 }
00100 size_ = static_cast<int>(end() - p);
00101 }
00102
00103 const char *end() const { return storage_ + sizeof(storage_); }
00104 char *end() { return storage_ + sizeof(storage_); }
00105
00106 bool is_neg_;
00107 int size_;
00108
00109 char storage_[128 / 3 + 1];
00110 };
00111
00112
00113
00114 string_view BaseIndicator(const ConvertedIntInfo &info,
00115 const ConversionSpec conv) {
00116 bool alt = conv.flags().alt;
00117 int radix = conv.conv().radix();
00118 if (conv.conv().id() == ConversionChar::p)
00119 alt = true;
00120
00121
00122
00123 if (alt && radix == 16 && !info.digits().empty()) {
00124 if (conv.conv().upper()) return "0X";
00125 return "0x";
00126 }
00127 return {};
00128 }
00129
00130 string_view SignColumn(bool neg, const ConversionSpec conv) {
00131 if (conv.conv().is_signed()) {
00132 if (neg) return "-";
00133 if (conv.flags().show_pos) return "+";
00134 if (conv.flags().sign_col) return " ";
00135 }
00136 return {};
00137 }
00138
00139 bool ConvertCharImpl(unsigned char v, const ConversionSpec conv,
00140 FormatSinkImpl *sink) {
00141 size_t fill = 0;
00142 if (conv.width() >= 0) fill = conv.width();
00143 ReducePadding(1, &fill);
00144 if (!conv.flags().left) sink->Append(fill, ' ');
00145 sink->Append(1, v);
00146 if (conv.flags().left) sink->Append(fill, ' ');
00147 return true;
00148 }
00149
00150 bool ConvertIntImplInner(const ConvertedIntInfo &info,
00151 const ConversionSpec conv, FormatSinkImpl *sink) {
00152
00153
00154 size_t fill = 0;
00155 if (conv.width() >= 0) fill = conv.width();
00156
00157 string_view formatted = info.digits();
00158 ReducePadding(formatted, &fill);
00159
00160 string_view sign = SignColumn(info.is_neg(), conv);
00161 ReducePadding(sign, &fill);
00162
00163 string_view base_indicator = BaseIndicator(info, conv);
00164 ReducePadding(base_indicator, &fill);
00165
00166 int precision = conv.precision();
00167 bool precision_specified = precision >= 0;
00168 if (!precision_specified)
00169 precision = 1;
00170
00171 if (conv.flags().alt && conv.conv().id() == ConversionChar::o) {
00172
00173
00174
00175 if (formatted.empty() || *formatted.begin() != '0') {
00176 int needed = static_cast<int>(formatted.size()) + 1;
00177 precision = std::max(precision, needed);
00178 }
00179 }
00180
00181 size_t num_zeroes = Excess(formatted.size(), precision);
00182 ReducePadding(num_zeroes, &fill);
00183
00184 size_t num_left_spaces = !conv.flags().left ? fill : 0;
00185 size_t num_right_spaces = conv.flags().left ? fill : 0;
00186
00187
00188
00189
00190 if (!precision_specified && conv.flags().zero) {
00191 num_zeroes += num_left_spaces;
00192 num_left_spaces = 0;
00193 }
00194
00195 sink->Append(num_left_spaces, ' ');
00196 sink->Append(sign);
00197 sink->Append(base_indicator);
00198 sink->Append(num_zeroes, '0');
00199 sink->Append(formatted);
00200 sink->Append(num_right_spaces, ' ');
00201 return true;
00202 }
00203
00204 template <typename T>
00205 bool ConvertIntImplInner(T v, const ConversionSpec conv, FormatSinkImpl *sink) {
00206 ConvertedIntInfo info(v, conv.conv());
00207 if (conv.flags().basic && conv.conv().id() != ConversionChar::p) {
00208 if (info.is_neg()) sink->Append(1, '-');
00209 if (info.digits().empty()) {
00210 sink->Append(1, '0');
00211 } else {
00212 sink->Append(info.digits());
00213 }
00214 return true;
00215 }
00216 return ConvertIntImplInner(info, conv, sink);
00217 }
00218
00219 template <typename T>
00220 bool ConvertIntArg(T v, const ConversionSpec conv, FormatSinkImpl *sink) {
00221 if (conv.conv().is_float()) {
00222 return FormatConvertImpl(static_cast<double>(v), conv, sink).value;
00223 }
00224 if (conv.conv().id() == ConversionChar::c)
00225 return ConvertCharImpl(static_cast<unsigned char>(v), conv, sink);
00226 if (!conv.conv().is_integral())
00227 return false;
00228 if (!conv.conv().is_signed() && IsSigned<T>::value) {
00229 using U = typename MakeUnsigned<T>::type;
00230 return FormatConvertImpl(static_cast<U>(v), conv, sink).value;
00231 }
00232 return ConvertIntImplInner(v, conv, sink);
00233 }
00234
00235 template <typename T>
00236 bool ConvertFloatArg(T v, const ConversionSpec conv, FormatSinkImpl *sink) {
00237 return conv.conv().is_float() && ConvertFloatImpl(v, conv, sink);
00238 }
00239
00240 inline bool ConvertStringArg(string_view v, const ConversionSpec conv,
00241 FormatSinkImpl *sink) {
00242 if (conv.conv().id() != ConversionChar::s)
00243 return false;
00244 if (conv.flags().basic) {
00245 sink->Append(v);
00246 return true;
00247 }
00248 return sink->PutPaddedString(v, conv.width(), conv.precision(),
00249 conv.flags().left);
00250 }
00251
00252 }
00253
00254
00255 ConvertResult<Conv::s> FormatConvertImpl(const std::string &v,
00256 const ConversionSpec conv,
00257 FormatSinkImpl *sink) {
00258 return {ConvertStringArg(v, conv, sink)};
00259 }
00260
00261 ConvertResult<Conv::s> FormatConvertImpl(string_view v,
00262 const ConversionSpec conv,
00263 FormatSinkImpl *sink) {
00264 return {ConvertStringArg(v, conv, sink)};
00265 }
00266
00267 ConvertResult<Conv::s | Conv::p> FormatConvertImpl(const char *v,
00268 const ConversionSpec conv,
00269 FormatSinkImpl *sink) {
00270 if (conv.conv().id() == ConversionChar::p)
00271 return {FormatConvertImpl(VoidPtr(v), conv, sink).value};
00272 size_t len;
00273 if (v == nullptr) {
00274 len = 0;
00275 } else if (conv.precision() < 0) {
00276 len = std::strlen(v);
00277 } else {
00278
00279 len = std::find(v, v + conv.precision(), '\0') - v;
00280 }
00281 return {ConvertStringArg(string_view(v, len), conv, sink)};
00282 }
00283
00284
00285 ConvertResult<Conv::p> FormatConvertImpl(VoidPtr v, const ConversionSpec conv,
00286 FormatSinkImpl *sink) {
00287 if (conv.conv().id() != ConversionChar::p)
00288 return {false};
00289 if (!v.value) {
00290 sink->Append("(nil)");
00291 return {true};
00292 }
00293 return {ConvertIntImplInner(v.value, conv, sink)};
00294 }
00295
00296
00297 FloatingConvertResult FormatConvertImpl(float v, const ConversionSpec conv,
00298 FormatSinkImpl *sink) {
00299 return {ConvertFloatArg(v, conv, sink)};
00300 }
00301 FloatingConvertResult FormatConvertImpl(double v, const ConversionSpec conv,
00302 FormatSinkImpl *sink) {
00303 return {ConvertFloatArg(v, conv, sink)};
00304 }
00305 FloatingConvertResult FormatConvertImpl(long double v,
00306 const ConversionSpec conv,
00307 FormatSinkImpl *sink) {
00308 return {ConvertFloatArg(v, conv, sink)};
00309 }
00310
00311
00312 IntegralConvertResult FormatConvertImpl(char v, const ConversionSpec conv,
00313 FormatSinkImpl *sink) {
00314 return {ConvertIntArg(v, conv, sink)};
00315 }
00316 IntegralConvertResult FormatConvertImpl(signed char v,
00317 const ConversionSpec conv,
00318 FormatSinkImpl *sink) {
00319 return {ConvertIntArg(v, conv, sink)};
00320 }
00321 IntegralConvertResult FormatConvertImpl(unsigned char v,
00322 const ConversionSpec conv,
00323 FormatSinkImpl *sink) {
00324 return {ConvertIntArg(v, conv, sink)};
00325 }
00326
00327
00328 IntegralConvertResult FormatConvertImpl(short v,
00329 const ConversionSpec conv,
00330 FormatSinkImpl *sink) {
00331 return {ConvertIntArg(v, conv, sink)};
00332 }
00333 IntegralConvertResult FormatConvertImpl(unsigned short v,
00334 const ConversionSpec conv,
00335 FormatSinkImpl *sink) {
00336 return {ConvertIntArg(v, conv, sink)};
00337 }
00338 IntegralConvertResult FormatConvertImpl(int v, const ConversionSpec conv,
00339 FormatSinkImpl *sink) {
00340 return {ConvertIntArg(v, conv, sink)};
00341 }
00342 IntegralConvertResult FormatConvertImpl(unsigned v, const ConversionSpec conv,
00343 FormatSinkImpl *sink) {
00344 return {ConvertIntArg(v, conv, sink)};
00345 }
00346 IntegralConvertResult FormatConvertImpl(long v,
00347 const ConversionSpec conv,
00348 FormatSinkImpl *sink) {
00349 return {ConvertIntArg(v, conv, sink)};
00350 }
00351 IntegralConvertResult FormatConvertImpl(unsigned long v,
00352 const ConversionSpec conv,
00353 FormatSinkImpl *sink) {
00354 return {ConvertIntArg(v, conv, sink)};
00355 }
00356 IntegralConvertResult FormatConvertImpl(long long v,
00357 const ConversionSpec conv,
00358 FormatSinkImpl *sink) {
00359 return {ConvertIntArg(v, conv, sink)};
00360 }
00361 IntegralConvertResult FormatConvertImpl(unsigned long long v,
00362 const ConversionSpec conv,
00363 FormatSinkImpl *sink) {
00364 return {ConvertIntArg(v, conv, sink)};
00365 }
00366 IntegralConvertResult FormatConvertImpl(absl::uint128 v,
00367 const ConversionSpec conv,
00368 FormatSinkImpl *sink) {
00369 return {ConvertIntArg(v, conv, sink)};
00370 }
00371
00372 ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_();
00373
00374
00375 }
00376
00377 }