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.
501#define TINYFORMAT_PASSARGS_TAIL_4 , v2, v3, v4502#define TINYFORMAT_PASSARGS_TAIL_5 , v2, v3, v4, v5503#define TINYFORMAT_PASSARGS_TAIL_6 , v2, v3, v4, v5, v6504#define TINYFORMAT_PASSARGS_TAIL_7 , v2, v3, v4, v5, v6, v7505#define TINYFORMAT_PASSARGS_TAIL_8 , v2, v3, v4, v5, v6, v7, v8506#define TINYFORMAT_PASSARGS_TAIL_9 , v2, v3, v4, v5, v6, v7, v8, v9507#define TINYFORMAT_PASSARGS_TAIL_10 , v2, v3, v4, v5, v6, v7, v8, v9, v10508#define TINYFORMAT_PASSARGS_TAIL_11 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11509#define TINYFORMAT_PASSARGS_TAIL_12 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12510#define TINYFORMAT_PASSARGS_TAIL_13 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13511#define TINYFORMAT_PASSARGS_TAIL_14 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14512#define TINYFORMAT_PASSARGS_TAIL_15 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15513#define TINYFORMAT_PASSARGS_TAIL_16 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16515#define TINYFORMAT_FOREACH_ARGNUM(m) \516m(1) m(2) m(3) m(4) m(5) m(6) m(7) m(8) m(9) m(10) m(11) m(12) m(13) m(14) m(15) m(16)517//[[[end]]]521namespace detail {523// Type-opaque holder for an argument to format(), with associated actions on524// the type held as explicit function pointers. This allows FormatArg's for525// each argument to be allocated as a homogeneous array inside FormatList526// whereas a naive implementation based on inheritance does not.527class FormatArg528{529public:530FormatArg() = default;532template<typename T>533explicit FormatArg(const T& value)534: m_value(static_cast<const void*>(&value)),535m_formatImpl(&formatImpl<T>),536m_toIntImpl(&toIntImpl<T>)537{ }539void format(std::ostream& out, const char* fmtBegin,540const char* fmtEnd, int ntrunc) const541{542TINYFORMAT_ASSERT(m_value);543TINYFORMAT_ASSERT(m_formatImpl);544m_formatImpl(out, fmtBegin, fmtEnd, ntrunc, m_value);545}547int toInt() const548{549TINYFORMAT_ASSERT(m_value);550TINYFORMAT_ASSERT(m_toIntImpl);551return m_toIntImpl(m_value);552}554private:555template<typename T>556TINYFORMAT_HIDDEN static void formatImpl(std::ostream& out, const char* fmtBegin,557const char* fmtEnd, int ntrunc, const void* value)558{559formatValue(out, fmtBegin, fmtEnd, ntrunc, *static_cast<const T*>(value));560}562template<typename T>563TINYFORMAT_HIDDEN static int toIntImpl(const void* value)564{565return convertToInt<T>::invoke(*static_cast<const T*>(value));566}568const void* m_value{nullptr};569void (*m_formatImpl)(std::ostream& out, const char* fmtBegin,570const char* fmtEnd, int ntrunc, const void* value){nullptr};571int (*m_toIntImpl)(const void* value){nullptr};572};575// Parse and return an integer from the string c, as atoi()576// On return, c is set to one past the end of the integer.577inline int parseIntAndAdvance(const char*& c)578{579int i = 0;580for (;*c >= '0' && *c <= '9'; ++c)581i = 10*i + (*c - '0');582return i;583}585// Parse width or precision `n` from format string pointer `c`, and advance it586// to the next character. If an indirection is requested with `*`, the argument587// is read from `args[argIndex]` and `argIndex` is incremented (or read588// from `args[n]` in positional mode). Returns true if one or more589// characters were read.590inline bool parseWidthOrPrecision(int& n, const char*& c, bool positionalMode,591const detail::FormatArg* args,592int& argIndex, int numArgs)593{594if (*c >= '0' && *c <= '9') {595n = parseIntAndAdvance(c);596}597else if (*c == '*') {598++c;599n = 0;600if (positionalMode) {601int pos = parseIntAndAdvance(c) - 1;602if (*c != '$')603TINYFORMAT_ERROR("tinyformat: Non-positional argument used after a positional one");604if (pos >= 0 && pos < numArgs)605n = args[pos].toInt();606else607TINYFORMAT_ERROR("tinyformat: Positional argument out of range");608++c;609}610else {611if (argIndex < numArgs)612n = args[argIndex++].toInt();613else614TINYFORMAT_ERROR("tinyformat: Not enough arguments to read variable width or precision");615}616}617else {618return false;619}620return true;621}623// Print literal part of format string and return next format spec position.624//625// Skips over any occurrences of '%%', printing a literal '%' to the output.626// The position of the first % character of the next nontrivial format spec is627// returned, or the end of string.628inline const char* printFormatStringLiteral(std::ostream& out, const char* fmt)629{630const char* c = fmt;631for (;; ++c) {632if (*c == '\0') {633out.write(fmt, c - fmt);634return c;635}636else if (*c == '%') {637out.write(fmt, c - fmt);638if (*(c+1) != '%')639return c;640// for "%%", tack trailing % onto next literal section.641fmt = ++c;642}643}644}647// Parse a format string and set the stream state accordingly.648//649// The format mini-language recognized here is meant to be the one from C99,650// with the form "%[flags][width][.precision][length]type" with POSIX651// positional arguments extension.652//653// POSIX positional arguments extension:654// Conversions can be applied to the nth argument after the format in655// the argument list, rather than to the next unused argument. In this case,656// the conversion specifier character % (see below) is replaced by the sequence657// "%n$", where n is a decimal integer in the range [1,{NL_ARGMAX}],658// giving the position of the argument in the argument list. This feature659// provides for the definition of format strings that select arguments660// in an order appropriate to specific languages.661//662// The format can contain either numbered argument conversion specifications663// (that is, "%n$" and "*m$"), or unnumbered argument conversion specifications664// (that is, % and * ), but not both. The only exception to this is that %%665// can be mixed with the "%n$" form. The results of mixing numbered and666// unnumbered argument specifications in a format string are undefined.667// When numbered argument specifications are used, specifying the Nth argument668// requires that all the leading arguments, from the first to the (N-1)th,669// are specified in the format string.670//671// In format strings containing the "%n$" form of conversion specification,672// numbered arguments in the argument list can be referenced from the format673// string as many times as required.674//675// Formatting options which can't be natively represented using the ostream676// state are returned in spacePadPositive (for space padded positive numbers)677// and ntrunc (for truncating conversions). argIndex is incremented if678// necessary to pull out variable width and precision. The function returns a679// pointer to the character after the end of the current format spec.680inline const char* streamStateFromFormat(std::ostream& out, bool& positionalMode,681bool& spacePadPositive,682int& ntrunc, const char* fmtStart,683const detail::FormatArg* args,684int& argIndex, int numArgs)685{686TINYFORMAT_ASSERT(*fmtStart == '%');687// Reset stream state to defaults.688out.width(0);689out.precision(6);690out.fill(' ');691// Reset most flags; ignore irrelevant unitbuf & skipws.692out.unsetf(std::ios::adjustfield | std::ios::basefield |693std::ios::floatfield | std::ios::showbase | std::ios::boolalpha |694std::ios::showpoint | std::ios::showpos | std::ios::uppercase);695bool precisionSet = false;696bool widthSet = false;697int widthExtra = 0;698const char* c = fmtStart + 1;700// 1) Parse an argument index (if followed by '$') or a width possibly701// preceded with '0' flag.702if (*c >= '0' && *c <= '9') {703const char tmpc = *c;704int value = parseIntAndAdvance(c);705if (*c == '$') {706// value is an argument index707if (value > 0 && value <= numArgs)708argIndex = value - 1;709else710TINYFORMAT_ERROR("tinyformat: Positional argument out of range");711++c;712positionalMode = true;713}714else if (positionalMode) {715TINYFORMAT_ERROR("tinyformat: Non-positional argument used after a positional one");716}717else {718if (tmpc == '0') {719// Use internal padding so that numeric values are720// formatted correctly, eg -00010 rather than 000-10721out.fill('0');722out.setf(std::ios::internal, std::ios::adjustfield);723}724if (value != 0) {725// Nonzero value means that we parsed width.726widthSet = true;727out.width(value);728}729}730}731else if (positionalMode) {732TINYFORMAT_ERROR("tinyformat: Non-positional argument used after a positional one");733}734// 2) Parse flags and width if we did not do it in previous step.735if (!widthSet) {736// Parse flags737for (;; ++c) {738switch (*c) {739case '#':740out.setf(std::ios::showpoint | std::ios::showbase);741continue;742case '0':743// overridden by left alignment ('-' flag)744if (!(out.flags() & std::ios::left)) {745// Use internal padding so that numeric values are746// formatted correctly, eg -00010 rather than 000-10747out.fill('0');748out.setf(std::ios::internal, std::ios::adjustfield);749}750continue;
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.