Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
751case '-':752out.fill(' ');753out.setf(std::ios::left, std::ios::adjustfield);754continue;755case ' ':756// overridden by show positive sign, '+' flag.757if (!(out.flags() & std::ios::showpos))758spacePadPositive = true;759continue;760case '+':761out.setf(std::ios::showpos);762spacePadPositive = false;763widthExtra = 1;764continue;765default:766break;767}768break;769}770// Parse width771int width = 0;772widthSet = parseWidthOrPrecision(width, c, positionalMode,773args, argIndex, numArgs);774if (widthSet) {775if (width < 0) {776// negative widths correspond to '-' flag set777out.fill(' ');778out.setf(std::ios::left, std::ios::adjustfield);779width = -width;780}781out.width(width);782}783}784// 3) Parse precision785if (*c == '.') {786++c;787int precision = 0;788parseWidthOrPrecision(precision, c, positionalMode,789args, argIndex, numArgs);790// Presence of `.` indicates precision set, unless the inferred value791// was negative in which case the default is used.792precisionSet = precision >= 0;793if (precisionSet)794out.precision(precision);795}796// 4) Ignore any C99 length modifier797while (*c == 'l' || *c == 'h' || *c == 'L' ||798*c == 'j' || *c == 'z' || *c == 't') {799++c;800}801// 5) We're up to the conversion specifier character.802// Set stream flags based on conversion specifier (thanks to the803// boost::format class for forging the way here).804bool intConversion = false;805switch (*c) {806case 'u': case 'd': case 'i':807out.setf(std::ios::dec, std::ios::basefield);808intConversion = true;809break;810case 'o':811out.setf(std::ios::oct, std::ios::basefield);812intConversion = true;813break;814case 'X':815out.setf(std::ios::uppercase);816[[fallthrough]];817case 'x': case 'p':818out.setf(std::ios::hex, std::ios::basefield);819intConversion = true;820break;821case 'E':822out.setf(std::ios::uppercase);823[[fallthrough]];824case 'e':825out.setf(std::ios::scientific, std::ios::floatfield);826out.setf(std::ios::dec, std::ios::basefield);827break;828case 'F':829out.setf(std::ios::uppercase);830[[fallthrough]];831case 'f':832out.setf(std::ios::fixed, std::ios::floatfield);833break;834case 'A':835out.setf(std::ios::uppercase);836[[fallthrough]];837case 'a':838# ifdef _MSC_VER839// Workaround https://developercommunity.visualstudio.com/content/problem/520472/hexfloat-stream-output-does-not-ignore-precision-a.html840// by always setting maximum precision on MSVC to avoid precision841// loss for doubles.842out.precision(13);843# endif844out.setf(std::ios::fixed | std::ios::scientific, std::ios::floatfield);845break;846case 'G':847out.setf(std::ios::uppercase);848[[fallthrough]];849case 'g':850out.setf(std::ios::dec, std::ios::basefield);851// As in boost::format, let stream decide float format.852out.flags(out.flags() & ~std::ios::floatfield);853break;854case 'c':855// Handled as special case inside formatValue()856break;857case 's':858if (precisionSet)859ntrunc = static_cast<int>(out.precision());860// Make %s print Booleans as "true" and "false"861out.setf(std::ios::boolalpha);862break;863case 'n':864// Not supported - will cause problems!865TINYFORMAT_ERROR("tinyformat: %n conversion spec not supported");866break;867case '\0':868TINYFORMAT_ERROR("tinyformat: Conversion spec incorrectly "869"terminated by end of string");870return c;871default:872break;873}874if (intConversion && precisionSet && !widthSet) {875// "precision" for integers gives the minimum number of digits (to be876// padded with zeros on the left). This isn't really supported by the877// iostreams, but we can approximately simulate it with the width if878// the width isn't otherwise used.879out.width(out.precision() + widthExtra);880out.setf(std::ios::internal, std::ios::adjustfield);881out.fill('0');882}883return c+1;884}887//------------------------------------------------------------------------------888inline void formatImpl(std::ostream& out, const char* fmt,889const detail::FormatArg* args,890int numArgs)891{892// Saved stream state893std::streamsize origWidth = out.width();894std::streamsize origPrecision = out.precision();895std::ios::fmtflags origFlags = out.flags();896char origFill = out.fill();898// "Positional mode" means all format specs should be of the form "%n$..."899// with `n` an integer. We detect this in `streamStateFromFormat`.900bool positionalMode = false;901int argIndex = 0;902while (true) {903fmt = printFormatStringLiteral(out, fmt);904if (*fmt == '\0') {905if (!positionalMode && argIndex < numArgs) {906TINYFORMAT_ERROR("tinyformat: Not enough conversion specifiers in format string");907}908break;909}910bool spacePadPositive = false;911int ntrunc = -1;912const char* fmtEnd = streamStateFromFormat(out, positionalMode, spacePadPositive, ntrunc, fmt,913args, argIndex, numArgs);914// NB: argIndex may be incremented by reading variable width/precision915// in `streamStateFromFormat`, so do the bounds check here.916if (argIndex >= numArgs) {917TINYFORMAT_ERROR("tinyformat: Too many conversion specifiers in format string");918return;919}920const FormatArg& arg = args[argIndex];921// Format the arg into the stream.922if (!spacePadPositive) {923arg.format(out, fmt, fmtEnd, ntrunc);924}925else {926// The following is a special case with no direct correspondence927// between stream formatting and the printf() behaviour. Simulate928// it crudely by formatting into a temporary string stream and929// munging the resulting string.930std::ostringstream tmpStream;931tmpStream.copyfmt(out);932tmpStream.setf(std::ios::showpos);933arg.format(tmpStream, fmt, fmtEnd, ntrunc);934std::string result = tmpStream.str(); // allocates... yuck.935for (size_t i = 0, iend = result.size(); i < iend; ++i) {936if (result[i] == '+')937result[i] = ' ';938}939out << result;940}941if (!positionalMode)942++argIndex;943fmt = fmtEnd;944}946// Restore stream state947out.width(origWidth);948out.precision(origPrecision);949out.flags(origFlags);950out.fill(origFill);951}953} // namespace detail956/// List of template arguments format(), held in a type-opaque way.957///958/// A const reference to FormatList (typedef'd as FormatListRef) may be959/// conveniently used to pass arguments to non-template functions: All type960/// information has been stripped from the arguments, leaving just enough of a961/// common interface to perform formatting as required.962class FormatList963{964public:965FormatList(detail::FormatArg* args, int N)966: m_args(args), m_N(N) { }968friend void vformat(std::ostream& out, const char* fmt,969const FormatList& list);971private:972const detail::FormatArg* m_args;973int m_N;974};976/// Reference to type-opaque format list for passing to vformat()977typedef const FormatList& FormatListRef;980namespace detail {982// Format list subclass with fixed storage to avoid dynamic allocation983template<int N>984class FormatListN : public FormatList985{986public:987#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES988template<typename... Args>989explicit FormatListN(const Args&... args)990: FormatList(&m_formatterStore[0], N),991m_formatterStore { FormatArg(args)... }992{ static_assert(sizeof...(args) == N, "Number of args must be N"); }993#else // C++98 version994void init(int) {}995# define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \996\997template<TINYFORMAT_ARGTYPES(n)> \998FormatListN(TINYFORMAT_VARARGS(n)) \999: FormatList(&m_formatterStore[0], n) \1000{ TINYFORMAT_ASSERT(n == N); init(0, TINYFORMAT_PASSARGS(n)); } \
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.