headers updated
This commit is contained in:
22
src/pos.cpp
22
src/pos.cpp
@@ -6,18 +6,20 @@
|
||||
// Stake cache by Qtum
|
||||
// Copyright (c) 2016-2018 The Qtum developers
|
||||
|
||||
#include "pos.h"
|
||||
#include <pos.h>
|
||||
|
||||
#include "chain.h"
|
||||
#include "chainparams.h"
|
||||
#include "clientversion.h"
|
||||
#include "coins.h"
|
||||
#include "hash.h"
|
||||
#include "main.h"
|
||||
#include "uint256.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include <base58.h>
|
||||
#include <chain.h>
|
||||
#include <chainparams.h>
|
||||
#include <clientversion.h>
|
||||
#include <coins.h>
|
||||
#include <hash.h>
|
||||
#include <main.h>
|
||||
#include <uint256.h>
|
||||
#include <primitives/block.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <stdio.h>
|
||||
#include "util.h"
|
||||
#include <util.h>
|
||||
|
||||
// Stake Modifier (hash modifier of proof-of-stake):
|
||||
// The purpose of stake modifier is to prevent a txout (coin) owner from
|
||||
|
||||
18
src/pos.h
18
src/pos.h
@@ -9,15 +9,15 @@
|
||||
#ifndef BLACKCOIN_POS_H
|
||||
#define BLACKCOIN_POS_H
|
||||
|
||||
#include "pos.h"
|
||||
#include "txdb.h"
|
||||
#include "main.h"
|
||||
#include "arith_uint256.h"
|
||||
#include "consensus/validation.h"
|
||||
#include "hash.h"
|
||||
#include "timedata.h"
|
||||
#include "chainparams.h"
|
||||
#include "script/sign.h"
|
||||
#include <pos.h>
|
||||
#include <txdb.h>
|
||||
#include <main.h>
|
||||
#include <arith_uint256.h>
|
||||
#include <consensus/validation.h>
|
||||
#include <hash.h>
|
||||
#include <timedata.h>
|
||||
#include <chainparams.h>
|
||||
#include <script/sign.h>
|
||||
#include <stdint.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
19
src/pow.cpp
19
src/pow.cpp
@@ -3,13 +3,13 @@
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "pow.h"
|
||||
#include <pow.h>
|
||||
|
||||
#include "arith_uint256.h"
|
||||
#include "chain.h"
|
||||
#include "primitives/block.h"
|
||||
#include "uint256.h"
|
||||
#include "util.h"
|
||||
#include <arith_uint256.h>
|
||||
#include <chain.h>
|
||||
#include <primitives/block.h>
|
||||
#include <uint256.h>
|
||||
#include <util.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static arith_uint256 GetTargetLimit(int64_t nTime, const Consensus::Params& params, bool fProofOfStake)
|
||||
@@ -33,15 +33,15 @@ unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, const CBlockHe
|
||||
unsigned int nTargetLimit = GetTargetLimit(pindexLast->GetBlockTime(), params, fProofOfStake).GetCompact();
|
||||
|
||||
// Genesis block
|
||||
if (pindexLast == NULL)
|
||||
if (pindexLast == nullptr)
|
||||
return UintToArith256(params.powLimit).GetCompact();
|
||||
|
||||
const CBlockIndex* pindexPrev = GetLastBlockIndex(pindexLast, fProofOfStake);
|
||||
|
||||
if (pindexPrev->pprev == NULL)
|
||||
if (pindexPrev->pprev == nullptr)
|
||||
return nTargetLimit; // first block
|
||||
const CBlockIndex* pindexPrevPrev = GetLastBlockIndex(pindexPrev->pprev, fProofOfStake);
|
||||
if (pindexPrevPrev->pprev == NULL)
|
||||
if (pindexPrevPrev->pprev == nullptr)
|
||||
return nTargetLimit; // second block
|
||||
|
||||
return CalculateNextTargetRequired(pindexPrev, pindexPrevPrev->GetBlockTime(), params, fProofOfStake);
|
||||
@@ -82,6 +82,7 @@ unsigned int CalculateNextTargetRequired(const CBlockIndex* pindexLast, int64_t
|
||||
|
||||
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params)
|
||||
{
|
||||
return true;
|
||||
bool fNegative;
|
||||
bool fOverflow;
|
||||
arith_uint256 bnTarget;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#ifndef BITCOIN_POW_H
|
||||
#define BITCOIN_POW_H
|
||||
|
||||
#include "consensus/params.h"
|
||||
#include <consensus/params.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "protocol.h"
|
||||
#include <protocol.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "utilstrencodings.h"
|
||||
#include <util.h>
|
||||
#include <utilstrencodings.h>
|
||||
|
||||
#ifndef WIN32
|
||||
# include <arpa/inet.h>
|
||||
|
||||
@@ -10,10 +10,11 @@
|
||||
#ifndef BITCOIN_PROTOCOL_H
|
||||
#define BITCOIN_PROTOCOL_H
|
||||
|
||||
#include "netaddress.h"
|
||||
#include "serialize.h"
|
||||
#include "uint256.h"
|
||||
#include "version.h"
|
||||
#include <netaddress.h>
|
||||
#include <netbase.h>
|
||||
#include <serialize.h>
|
||||
#include <uint256.h>
|
||||
#include <version.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
@@ -66,7 +67,7 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* Bitcoin protocol message types. When adding new message types, don't forget
|
||||
* Blackcoin protocol message types. When adding new message types, don't forget
|
||||
* to update allNetMessageTypes in protocol.cpp.
|
||||
*/
|
||||
namespace NetMsgType {
|
||||
@@ -255,21 +256,21 @@ enum ServiceFlags : uint64_t {
|
||||
// Nothing
|
||||
NODE_NONE = 0,
|
||||
// NODE_NETWORK means that the node is capable of serving the block chain. It is currently
|
||||
// set by all Bitcoin Core nodes, and is unset by SPV clients or other peers that just want
|
||||
// set by all Blackcoin More nodes, and is unset by SPV clients or other peers that just want
|
||||
// network services but don't provide them.
|
||||
NODE_NETWORK = (1 << 0),
|
||||
// NODE_GETUTXO means the node is capable of responding to the getutxo protocol request.
|
||||
// Bitcoin Core does not support this but a patch set called Bitcoin XT does.
|
||||
// Blackcoin More does not support this but a patch set called Bitcoin XT does.
|
||||
// See BIP 64 for details on how this is implemented.
|
||||
NODE_GETUTXO = (1 << 1),
|
||||
// NODE_BLOOM means the node is capable and willing to handle bloom-filtered connections.
|
||||
// Bitcoin Core nodes used to support this by default, without advertising this bit,
|
||||
// Blackcoin More nodes used to support this by default, without advertising this bit,
|
||||
// but no longer do as of protocol version 70011 (= NO_BLOOM_VERSION)
|
||||
NODE_BLOOM = (1 << 2),
|
||||
|
||||
// Bits 24-31 are reserved for temporary experiments. Just pick a bit that
|
||||
// isn't getting used, or one not being used much, and notify the
|
||||
// bitcoin-development mailing list. Remember that service bits are just
|
||||
// Blackcoin development support channels. Remember that service bits are just
|
||||
// unauthenticated advertisements, so your code must be robust against
|
||||
// collisions and other cases where nodes may be advertising a service they
|
||||
// do not actually support. Other service bits should be allocated via the
|
||||
@@ -318,8 +319,9 @@ const uint32_t MSG_TYPE_MASK = 0xffffffff >> 2;
|
||||
enum GetDataMsg
|
||||
{
|
||||
UNDEFINED = 0,
|
||||
MSG_TX = 1,
|
||||
MSG_TX,
|
||||
MSG_BLOCK,
|
||||
MSG_TYPE_MAX = MSG_BLOCK,
|
||||
// The following can only occur in getdata. Invs always use TX or BLOCK.
|
||||
MSG_FILTERED_BLOCK,
|
||||
/*
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "pubkey.h"
|
||||
#include <pubkey.h>
|
||||
|
||||
#include <secp256k1.h>
|
||||
#include <secp256k1_recovery.h>
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace
|
||||
{
|
||||
/* Global secp256k1_context object used for verification. */
|
||||
secp256k1_context* secp256k1_context_verify = NULL;
|
||||
secp256k1_context* secp256k1_context_verify = nullptr;
|
||||
}
|
||||
|
||||
/** This function is taken from the libsecp256k1 distribution and implements
|
||||
@@ -277,7 +277,7 @@ bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const {
|
||||
if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, &vchSig[0], vchSig.size())) {
|
||||
return false;
|
||||
}
|
||||
return (!secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, NULL, &sig));
|
||||
return (!secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, nullptr, &sig));
|
||||
}
|
||||
|
||||
int CompareBigEndian(const unsigned char *c1, size_t c1len, const unsigned char *c2, size_t c2len) {
|
||||
@@ -334,9 +334,9 @@ bool CPubKey::CheckSignatureElement(const unsigned char *vch, int len, bool half
|
||||
ECCVerifyHandle::ECCVerifyHandle()
|
||||
{
|
||||
if (refcount == 0) {
|
||||
assert(secp256k1_context_verify == NULL);
|
||||
assert(secp256k1_context_verify == nullptr);
|
||||
secp256k1_context_verify = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
|
||||
assert(secp256k1_context_verify != NULL);
|
||||
assert(secp256k1_context_verify != nullptr);
|
||||
}
|
||||
refcount++;
|
||||
}
|
||||
@@ -345,8 +345,8 @@ ECCVerifyHandle::~ECCVerifyHandle()
|
||||
{
|
||||
refcount--;
|
||||
if (refcount == 0) {
|
||||
assert(secp256k1_context_verify != NULL);
|
||||
assert(secp256k1_context_verify != nullptr);
|
||||
secp256k1_context_destroy(secp256k1_context_verify);
|
||||
secp256k1_context_verify = NULL;
|
||||
secp256k1_context_verify = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
#ifndef BITCOIN_PUBKEY_H
|
||||
#define BITCOIN_PUBKEY_H
|
||||
|
||||
#include "hash.h"
|
||||
#include "serialize.h"
|
||||
#include "uint256.h"
|
||||
#include <hash.h>
|
||||
#include <serialize.h>
|
||||
#include <uint256.h>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
@@ -217,7 +217,7 @@ struct CExtPubKey {
|
||||
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
|
||||
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
|
||||
bool Derive(CExtPubKey& out, unsigned int nChild) const;
|
||||
|
||||
|
||||
unsigned int GetSerializeSize(int nType, int nVersion) const
|
||||
{
|
||||
return BIP32_EXTKEY_SIZE+1; //add one byte for the size (compact int)
|
||||
|
||||
@@ -3,20 +3,19 @@
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "random.h"
|
||||
#include <random.h>
|
||||
|
||||
#include "crypto/sha512.h"
|
||||
#include "support/cleanse.h"
|
||||
#include <crypto/sha512.h>
|
||||
#include <support/cleanse.h>
|
||||
#ifdef WIN32
|
||||
#include "compat.h" // for Windows API
|
||||
#include <compat.h> // for Windows API
|
||||
#include <wincrypt.h>
|
||||
#endif
|
||||
#include "serialize.h" // for begin_ptr(vec)
|
||||
#include "util.h" // for LogPrint()
|
||||
#include "utilstrencodings.h" // for GetTime()
|
||||
#include <serialize.h> // for begin_ptr(vec)
|
||||
#include <util.h> // for LogPrint()
|
||||
#include <utilstrencodings.h> // for GetTime()
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <limits>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/time.h>
|
||||
@@ -38,7 +37,7 @@ static inline int64_t GetPerformanceCounter()
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
|
||||
#else
|
||||
timeval t;
|
||||
gettimeofday(&t, NULL);
|
||||
gettimeofday(&t, nullptr);
|
||||
nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec);
|
||||
#endif
|
||||
return nCounter;
|
||||
@@ -72,7 +71,7 @@ static void RandAddSeedPerfmon()
|
||||
const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
|
||||
while (true) {
|
||||
nSize = vData.size();
|
||||
ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, begin_ptr(vData), &nSize);
|
||||
ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", nullptr, nullptr, begin_ptr(vData), &nSize);
|
||||
if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
|
||||
break;
|
||||
vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
|
||||
@@ -97,7 +96,7 @@ static void GetOSRand(unsigned char *ent32)
|
||||
{
|
||||
#ifdef WIN32
|
||||
HCRYPTPROV hProvider;
|
||||
int ret = CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
|
||||
int ret = CryptAcquireContextW(&hProvider, nullptr, nullptr, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
|
||||
if (!ret) {
|
||||
RandFailure();
|
||||
}
|
||||
@@ -219,4 +218,4 @@ FastRandomContext::FastRandomContext(bool fDeterministic)
|
||||
} while (tmp == 0 || tmp == 0x464fffffU);
|
||||
Rw = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
42
src/random.h
42
src/random.h
@@ -6,7 +6,9 @@
|
||||
#ifndef BITCOIN_RANDOM_H
|
||||
#define BITCOIN_RANDOM_H
|
||||
|
||||
#include "uint256.h"
|
||||
#include <uint256.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -33,13 +35,29 @@ void GetStrongRandBytes(unsigned char* buf, int num);
|
||||
*/
|
||||
void seed_insecure_rand(bool fDeterministic = false);
|
||||
|
||||
/**
|
||||
* MWC RNG of George Marsaglia
|
||||
* This is intended to be fast. It has a period of 2^59.3, though the
|
||||
* least significant 16 bits only have a period of about 2^30.1.
|
||||
*
|
||||
* @return random value
|
||||
*/
|
||||
extern uint32_t insecure_rand_Rz;
|
||||
extern uint32_t insecure_rand_Rw;
|
||||
static inline uint32_t insecure_rand(void)
|
||||
{
|
||||
insecure_rand_Rz = 36969 * (insecure_rand_Rz & 65535) + (insecure_rand_Rz >> 16);
|
||||
insecure_rand_Rw = 18000 * (insecure_rand_Rw & 65535) + (insecure_rand_Rw >> 16);
|
||||
return (insecure_rand_Rw << 16) + insecure_rand_Rz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fast randomness source. This is seeded once with secure random data, but
|
||||
* is completely deterministic and insecure after that.
|
||||
* is completely deterministic and does not gather more entropy after that.
|
||||
*
|
||||
* This class is not thread-safe.
|
||||
*/
|
||||
class FastRandomContext
|
||||
{
|
||||
class FastRandomContext {
|
||||
private:
|
||||
uint64_t bitbuf;
|
||||
int bitbuf_size;
|
||||
@@ -94,20 +112,4 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* MWC RNG of George Marsaglia
|
||||
* This is intended to be fast. It has a period of 2^59.3, though the
|
||||
* least significant 16 bits only have a period of about 2^30.1.
|
||||
*
|
||||
* @return random value
|
||||
*/
|
||||
extern uint32_t insecure_rand_Rz;
|
||||
extern uint32_t insecure_rand_Rw;
|
||||
static inline uint32_t insecure_rand(void)
|
||||
{
|
||||
insecure_rand_Rz = 36969 * (insecure_rand_Rz & 65535) + (insecure_rand_Rz >> 16);
|
||||
insecure_rand_Rw = 18000 * (insecure_rand_Rw & 65535) + (insecure_rand_Rw >> 16);
|
||||
return (insecure_rand_Rw << 16) + insecure_rand_Rz;
|
||||
}
|
||||
|
||||
#endif // BITCOIN_RANDOM_H
|
||||
|
||||
48
src/rest.cpp
48
src/rest.cpp
@@ -3,20 +3,21 @@
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "chain.h"
|
||||
#include "chainparams.h"
|
||||
#include "primitives/block.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "main.h"
|
||||
#include "httpserver.h"
|
||||
#include "rpc/server.h"
|
||||
#include "streams.h"
|
||||
#include "sync.h"
|
||||
#include "txmempool.h"
|
||||
#include "utilstrencodings.h"
|
||||
#include "version.h"
|
||||
#include <chain.h>
|
||||
#include <chainparams.h>
|
||||
#include <primitives/block.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <main.h>
|
||||
#include <httpserver.h>
|
||||
#include <rpc/server.h>
|
||||
#include <streams.h>
|
||||
#include <sync.h>
|
||||
#include <txmempool.h>
|
||||
#include <utilstrencodings.h>
|
||||
#include <version.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/dynamic_bitset.hpp>
|
||||
|
||||
#include <univalue.h>
|
||||
|
||||
@@ -138,7 +139,7 @@ static bool rest_headers(HTTPRequest* req,
|
||||
if (path.size() != 2)
|
||||
return RESTERR(req, HTTP_BAD_REQUEST, "No header count specified. Use /rest/headers/<count>/<hash>.<ext>.");
|
||||
|
||||
long count = strtol(path[0].c_str(), NULL, 10);
|
||||
long count = strtol(path[0].c_str(), nullptr, 10);
|
||||
if (count < 1 || count > 2000)
|
||||
return RESTERR(req, HTTP_BAD_REQUEST, "Header count out of range: " + path[0]);
|
||||
|
||||
@@ -152,7 +153,7 @@ static bool rest_headers(HTTPRequest* req,
|
||||
{
|
||||
LOCK(cs_main);
|
||||
BlockMap::const_iterator it = mapBlockIndex.find(hash);
|
||||
const CBlockIndex *pindex = (it != mapBlockIndex.end()) ? it->second : NULL;
|
||||
const CBlockIndex *pindex = (it != mapBlockIndex.end()) ? it->second : nullptr;
|
||||
while (pindex != NULL && chainActive.Contains(pindex)) {
|
||||
headers.push_back(pindex);
|
||||
if (headers.size() == (unsigned long)count)
|
||||
@@ -162,7 +163,7 @@ static bool rest_headers(HTTPRequest* req,
|
||||
}
|
||||
|
||||
CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION);
|
||||
BOOST_FOREACH(const CBlockIndex *pindex, headers) {
|
||||
for(const CBlockIndex *pindex: headers) {
|
||||
ssHeader << pindex->GetBlockHeader();
|
||||
}
|
||||
|
||||
@@ -182,7 +183,7 @@ static bool rest_headers(HTTPRequest* req,
|
||||
}
|
||||
case RF_JSON: {
|
||||
UniValue jsonHeaders(UniValue::VARR);
|
||||
BOOST_FOREACH(const CBlockIndex *pindex, headers) {
|
||||
for(const CBlockIndex *pindex: headers) {
|
||||
jsonHeaders.push_back(blockheaderToJSON(pindex));
|
||||
}
|
||||
string strJSON = jsonHeaders.write() + "\n";
|
||||
@@ -213,7 +214,7 @@ static bool rest_block(HTTPRequest* req,
|
||||
return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hashStr);
|
||||
|
||||
CBlock block;
|
||||
CBlockIndex* pblockindex = NULL;
|
||||
CBlockIndex* pblockindex = nullptr;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
if (mapBlockIndex.count(hash) == 0)
|
||||
@@ -500,8 +501,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
|
||||
vector<unsigned char> bitmap;
|
||||
vector<CCoin> outs;
|
||||
std::string bitmapStringRepresentation;
|
||||
std::vector<bool> hits;
|
||||
bitmap.resize((vOutPoints.size() + 7) / 8);
|
||||
boost::dynamic_bitset<unsigned char> hits(vOutPoints.size());
|
||||
{
|
||||
LOCK2(cs_main, mempool.cs);
|
||||
|
||||
@@ -517,11 +517,10 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
|
||||
for (size_t i = 0; i < vOutPoints.size(); i++) {
|
||||
CCoins coins;
|
||||
uint256 hash = vOutPoints[i].hash;
|
||||
bool hit = false;
|
||||
if (view.GetCoins(hash, coins)) {
|
||||
mempool.pruneSpent(hash, coins);
|
||||
if (coins.IsAvailable(vOutPoints[i].n)) {
|
||||
hit = true;
|
||||
hits[i] = true;
|
||||
// Safe to index into vout here because IsAvailable checked if it's off the end of the array, or if
|
||||
// n is valid but points to an already spent output (IsNull).
|
||||
CCoin coin;
|
||||
@@ -533,11 +532,10 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
|
||||
}
|
||||
}
|
||||
|
||||
hits.push_back(hit);
|
||||
bitmapStringRepresentation.append(hit ? "1" : "0"); // form a binary string representation (human-readable for json output)
|
||||
bitmap[i / 8] |= ((uint8_t)hit) << (i % 8);
|
||||
bitmapStringRepresentation.append(hits[i] ? "1" : "0"); // form a binary string representation (human-readable for json output)
|
||||
}
|
||||
}
|
||||
boost::to_block_range(hits, std::back_inserter(bitmap));
|
||||
|
||||
switch (rf) {
|
||||
case RF_BINARY: {
|
||||
@@ -572,7 +570,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
|
||||
objGetUTXOResponse.push_back(Pair("bitmap", bitmapStringRepresentation));
|
||||
|
||||
UniValue utxos(UniValue::VARR);
|
||||
BOOST_FOREACH (const CCoin& coin, outs) {
|
||||
for(const CCoin& coin: outs) {
|
||||
UniValue utxo(UniValue::VOBJ);
|
||||
utxo.push_back(Pair("txvers", (int32_t)coin.nTxVer));
|
||||
utxo.push_back(Pair("height", (int32_t)coin.nHeight));
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "scheduler.h"
|
||||
#include <scheduler.h>
|
||||
|
||||
#include "reverselock.h"
|
||||
#include <reverselock.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <boost/bind.hpp>
|
||||
@@ -54,10 +54,9 @@ void CScheduler::serviceQueue()
|
||||
#else
|
||||
// Some boost versions have a conflicting overload of wait_until that returns void.
|
||||
// Explicitly use a template here to avoid hitting that overload.
|
||||
while (!shouldStop() && !taskQueue.empty()) {
|
||||
boost::chrono::system_clock::time_point timeToWaitFor = taskQueue.begin()->first;
|
||||
if (newTaskScheduled.wait_until<>(lock, timeToWaitFor) == boost::cv_status::timeout)
|
||||
break; // Exit loop after timeout, it means we reached the time of the event
|
||||
while (!shouldStop() && !taskQueue.empty() &&
|
||||
newTaskScheduled.wait_until<>(lock, taskQueue.begin()->first) != boost::cv_status::timeout) {
|
||||
// Keep waiting until timeout
|
||||
}
|
||||
#endif
|
||||
// If there are multiple threads, the queue can empty while we're waiting (another
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#ifndef BITCOIN_SERIALIZE_H
|
||||
#define BITCOIN_SERIALIZE_H
|
||||
|
||||
#include "compat/endian.h"
|
||||
#include <compat/endian.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
@@ -44,7 +44,7 @@ inline T* NCONST_PTR(const T* val)
|
||||
return const_cast<T*>(val);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Get begin pointer of vector (non-const version).
|
||||
* @note These functions avoid the undefined case of indexing into an empty
|
||||
* vector, as well as that of indexing after the end of the vector.
|
||||
@@ -91,6 +91,11 @@ template<typename Stream> inline void ser_writedata32(Stream &s, uint32_t obj)
|
||||
obj = htole32(obj);
|
||||
s.write((char*)&obj, 4);
|
||||
}
|
||||
template<typename Stream> inline void ser_writedata32be(Stream &s, uint32_t obj)
|
||||
{
|
||||
obj = htobe32(obj);
|
||||
s.write((char*)&obj, 4);
|
||||
}
|
||||
template<typename Stream> inline void ser_writedata64(Stream &s, uint64_t obj)
|
||||
{
|
||||
obj = htole64(obj);
|
||||
@@ -114,6 +119,12 @@ template<typename Stream> inline uint32_t ser_readdata32(Stream &s)
|
||||
s.read((char*)&obj, 4);
|
||||
return le32toh(obj);
|
||||
}
|
||||
template<typename Stream> inline uint32_t ser_readdata32be(Stream &s)
|
||||
{
|
||||
uint32_t obj;
|
||||
s.read((char*)&obj, 4);
|
||||
return be32toh(obj);
|
||||
}
|
||||
template<typename Stream> inline uint64_t ser_readdata64(Stream &s)
|
||||
{
|
||||
uint64_t obj;
|
||||
@@ -158,15 +169,16 @@ enum
|
||||
SER_NETWORK = (1 << 0),
|
||||
SER_DISK = (1 << 1),
|
||||
SER_GETHASH = (1 << 2),
|
||||
SER_BLOCKHEADERONLY = (1 << 17),
|
||||
};
|
||||
|
||||
#define READWRITE(obj) (::SerReadWrite(s, (obj), nType, nVersion, ser_action))
|
||||
|
||||
/**
|
||||
/**
|
||||
* Implement three methods for serializable objects. These are actually wrappers over
|
||||
* "SerializationOp" template, which implements the body of each class' serialization
|
||||
* code. Adding "ADD_SERIALIZE_METHODS" in the body of the class causes these wrappers to be
|
||||
* added as members.
|
||||
* added as members.
|
||||
*/
|
||||
#define ADD_SERIALIZE_METHODS \
|
||||
size_t GetSerializeSize(int nType, int nVersion) const { \
|
||||
@@ -309,21 +321,21 @@ uint64_t ReadCompactSize(Stream& is)
|
||||
* sure the encoding is one-to-one, one is subtracted from all but the last digit.
|
||||
* Thus, the byte sequence a[] with length len, where all but the last byte
|
||||
* has bit 128 set, encodes the number:
|
||||
*
|
||||
*
|
||||
* (a[len-1] & 0x7F) + sum(i=1..len-1, 128^i*((a[len-i-1] & 0x7F)+1))
|
||||
*
|
||||
*
|
||||
* Properties:
|
||||
* * Very small (0-127: 1 byte, 128-16511: 2 bytes, 16512-2113663: 3 bytes)
|
||||
* * Every integer has exactly one encoding
|
||||
* * Encoding does not depend on size of original integer type
|
||||
* * No redundancy: every (infinite) byte sequence corresponds to a list
|
||||
* of encoded integers.
|
||||
*
|
||||
*
|
||||
* 0: [0x00] 256: [0x81 0x00]
|
||||
* 1: [0x01] 16383: [0xFE 0x7F]
|
||||
* 127: [0x7F] 16384: [0xFF 0x00]
|
||||
* 128: [0x80 0x00] 16511: [0xFF 0x7F]
|
||||
* 255: [0x80 0x7F] 65535: [0x82 0xFE 0x7F]
|
||||
* 128: [0x80 0x00] 16511: [0x80 0xFF 0x7F]
|
||||
* 255: [0x80 0x7F] 65535: [0x82 0xFD 0x7F]
|
||||
* 2^32: [0x8E 0xFE 0xFE 0xFF 0x00]
|
||||
*/
|
||||
|
||||
@@ -379,7 +391,7 @@ I ReadVarInt(Stream& is)
|
||||
*/
|
||||
#define LIMITED_STRING(obj,n) REF(LimitedString< n >(REF(obj)))
|
||||
|
||||
/**
|
||||
/**
|
||||
* Wrapper for serializing arrays and POD.
|
||||
*/
|
||||
class CFlatData
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#ifndef BITCOIN_STREAMS_H
|
||||
#define BITCOIN_STREAMS_H
|
||||
|
||||
#include "support/allocators/zeroafterfree.h"
|
||||
#include "serialize.h"
|
||||
#include <support/allocators/zeroafterfree.h>
|
||||
#include <serialize.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
|
||||
19
src/sync.cpp
19
src/sync.cpp
@@ -2,14 +2,13 @@
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "sync.h"
|
||||
#include <sync.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "utilstrencodings.h"
|
||||
#include <util.h>
|
||||
#include <utilstrencodings.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
#ifdef DEBUG_LOCKCONTENTION
|
||||
@@ -89,7 +88,7 @@ static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch,
|
||||
|
||||
LogPrintf("POTENTIAL DEADLOCK DETECTED\n");
|
||||
LogPrintf("Previous lock order was:\n");
|
||||
BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, s2) {
|
||||
for(const PAIRTYPE(void*, CLockLocation) & i: s2) {
|
||||
if (i.first == mismatch.first) {
|
||||
LogPrintf(" (1)");
|
||||
if (!firstLocked && secondLocked && i.second.fTry)
|
||||
@@ -107,7 +106,7 @@ static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch,
|
||||
firstLocked = false;
|
||||
secondLocked = false;
|
||||
LogPrintf("Current lock order is:\n");
|
||||
BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, s1) {
|
||||
for(const PAIRTYPE(void*, CLockLocation) & i: s1) {
|
||||
if (i.first == mismatch.first) {
|
||||
LogPrintf(" (1)");
|
||||
if (!firstLocked && secondLocked && i.second.fTry)
|
||||
@@ -127,7 +126,7 @@ static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch,
|
||||
|
||||
static void push_lock(void* c, const CLockLocation& locklocation, bool fTry)
|
||||
{
|
||||
if (lockstack.get() == NULL)
|
||||
if (lockstack.get() == nullptr)
|
||||
lockstack.reset(new LockStack);
|
||||
|
||||
boost::unique_lock<boost::mutex> lock(lockdata.dd_mutex);
|
||||
@@ -135,7 +134,7 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry)
|
||||
(*lockstack).push_back(std::make_pair(c, locklocation));
|
||||
|
||||
if (!fTry) {
|
||||
BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, (*lockstack)) {
|
||||
for(const PAIRTYPE(void*, CLockLocation) & i: (*lockstack)) {
|
||||
if (i.first == c)
|
||||
break;
|
||||
|
||||
@@ -170,14 +169,14 @@ void LeaveCritical()
|
||||
std::string LocksHeld()
|
||||
{
|
||||
std::string result;
|
||||
BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, *lockstack)
|
||||
for(const PAIRTYPE(void*, CLockLocation) & i: *lockstack)
|
||||
result += i.second.ToString() + std::string("\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs)
|
||||
{
|
||||
BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, *lockstack)
|
||||
for(const PAIRTYPE(void*, CLockLocation) & i: *lockstack)
|
||||
if (i.first == cs)
|
||||
return;
|
||||
fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str());
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#ifndef BITCOIN_SYNC_H
|
||||
#define BITCOIN_SYNC_H
|
||||
|
||||
#include "threadsafety.h"
|
||||
#include <threadsafety.h>
|
||||
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
|
||||
@@ -3,18 +3,17 @@
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config/bitcoin-config.h"
|
||||
#include <config/bitcoin-config.h>
|
||||
#endif
|
||||
|
||||
#include "timedata.h"
|
||||
#include <timedata.h>
|
||||
|
||||
#include "netaddress.h"
|
||||
#include "sync.h"
|
||||
#include "ui_interface.h"
|
||||
#include "util.h"
|
||||
#include "utilstrencodings.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <netaddress.h>
|
||||
#include <netbase.h>
|
||||
#include <sync.h>
|
||||
#include <ui_interface.h>
|
||||
#include <util.h>
|
||||
#include <utilstrencodings.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -96,7 +95,7 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
|
||||
{
|
||||
// If nobody has a time different than ours but within 5 minutes of ours, give a warning
|
||||
bool fMatch = false;
|
||||
BOOST_FOREACH(int64_t nOffset, vSorted)
|
||||
for(int64_t nOffset: vSorted)
|
||||
if (nOffset != 0 && abs64(nOffset) < 5 * 60)
|
||||
fMatch = true;
|
||||
|
||||
@@ -110,7 +109,7 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_FOREACH(int64_t n, vSorted)
|
||||
for(int64_t n: vSorted)
|
||||
LogPrint("net", "%+d ", n);
|
||||
LogPrint("net", "| ");
|
||||
|
||||
|
||||
710
src/tinyformat.h
710
src/tinyformat.h
@@ -123,7 +123,7 @@ namespace tinyformat {}
|
||||
namespace tfm = tinyformat;
|
||||
|
||||
// Error handling; calls assert() by default.
|
||||
#define TINYFORMAT_ERROR(reasonString) throw std::runtime_error(reasonString)
|
||||
#define TINYFORMAT_ERROR(reasonString) throw tinyformat::format_error(reasonString)
|
||||
|
||||
// Define for C++11 variadic templates which make the code shorter & more
|
||||
// general. If you don't define this, C++11 support is autodetected below.
|
||||
@@ -148,14 +148,6 @@ namespace tfm = tinyformat;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define TINYFORMAT_NOINLINE __attribute__((noinline))
|
||||
#elif defined(_MSC_VER)
|
||||
# define TINYFORMAT_NOINLINE __declspec(noinline)
|
||||
#else
|
||||
# define TINYFORMAT_NOINLINE
|
||||
#endif
|
||||
|
||||
#if defined(__GLIBCXX__) && __GLIBCXX__ < 20080201
|
||||
// std::showpos is broken on old libstdc++ as provided with OSX. See
|
||||
// http://gcc.gnu.org/ml/libstdc++/2007-11/msg00075.html
|
||||
@@ -172,6 +164,13 @@ namespace tfm = tinyformat;
|
||||
|
||||
namespace tinyformat {
|
||||
|
||||
class format_error: public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit format_error(const std::string &what): std::runtime_error(what) {
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
namespace detail {
|
||||
|
||||
@@ -270,6 +269,29 @@ struct convertToInt<T,true>
|
||||
static int invoke(const T& value) { return static_cast<int>(value); }
|
||||
};
|
||||
|
||||
// Format at most ntrunc characters to the given stream.
|
||||
template<typename T>
|
||||
inline void formatTruncated(std::ostream& out, const T& value, int ntrunc)
|
||||
{
|
||||
std::ostringstream tmp;
|
||||
tmp << value;
|
||||
std::string result = tmp.str();
|
||||
out.write(result.c_str(), (std::min)(ntrunc, static_cast<int>(result.size())));
|
||||
}
|
||||
#define TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(type) \
|
||||
inline void formatTruncated(std::ostream& out, type* value, int ntrunc) \
|
||||
{ \
|
||||
std::streamsize len = 0; \
|
||||
while(len < ntrunc && value[len] != 0) \
|
||||
++len; \
|
||||
out.write(value, len); \
|
||||
}
|
||||
// Overload for const char* and char*. Could overload for signed & unsigned
|
||||
// char too, but these are technically unneeded for printf compatibility.
|
||||
TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(const char)
|
||||
TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(char)
|
||||
#undef TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
@@ -278,18 +300,20 @@ struct convertToInt<T,true>
|
||||
// desired.
|
||||
|
||||
|
||||
// Format a value into a stream. Called from format() for all types by default.
|
||||
//
|
||||
// Users may override this for their own types. When this function is called,
|
||||
// the stream flags will have been modified according to the format string.
|
||||
// The format specification is provided in the range [fmtBegin, fmtEnd).
|
||||
//
|
||||
// By default, formatValue() uses the usual stream insertion operator
|
||||
// operator<< to format the type T, with special cases for the %c and %p
|
||||
// conversions.
|
||||
/// Format a value into a stream, delegating to operator<< by default.
|
||||
///
|
||||
/// Users may override this for their own types. When this function is called,
|
||||
/// the stream flags will have been modified according to the format string.
|
||||
/// The format specification is provided in the range [fmtBegin, fmtEnd). For
|
||||
/// truncating conversions, ntrunc is set to the desired maximum number of
|
||||
/// characters, for example "%.7s" calls formatValue with ntrunc = 7.
|
||||
///
|
||||
/// By default, formatValue() uses the usual stream insertion operator
|
||||
/// operator<< to format the type T, with special cases for the %c and %p
|
||||
/// conversions.
|
||||
template<typename T>
|
||||
inline void formatValue(std::ostream& out, const char* /*fmtBegin*/,
|
||||
const char* fmtEnd, const T& value)
|
||||
const char* fmtEnd, int ntrunc, const T& value)
|
||||
{
|
||||
#ifndef TINYFORMAT_ALLOW_WCHAR_STRINGS
|
||||
// Since we don't support printing of wchar_t using "%ls", make it fail at
|
||||
@@ -311,6 +335,12 @@ inline void formatValue(std::ostream& out, const char* /*fmtBegin*/,
|
||||
#ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
|
||||
else if(detail::formatZeroIntegerWorkaround<T>::invoke(out, value)) /**/;
|
||||
#endif
|
||||
else if(ntrunc >= 0)
|
||||
{
|
||||
// Take care not to overread C strings in truncating conversions like
|
||||
// "%.4s" where at most 4 characters may be read.
|
||||
detail::formatTruncated(out, value, ntrunc);
|
||||
}
|
||||
else
|
||||
out << value;
|
||||
}
|
||||
@@ -458,225 +488,99 @@ cog.outl('#define TINYFORMAT_FOREACH_ARGNUM(m) \\\n ' +
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Class holding current position in format string and an output stream into
|
||||
// which arguments are formatted.
|
||||
class FormatIterator
|
||||
// Type-opaque holder for an argument to format(), with associated actions on
|
||||
// the type held as explicit function pointers. This allows FormatArg's for
|
||||
// each argument to be allocated as a homogenous array inside FormatList
|
||||
// whereas a naive implementation based on inheritance does not.
|
||||
class FormatArg
|
||||
{
|
||||
public:
|
||||
// Flags for features not representable with standard stream state
|
||||
enum ExtraFormatFlags
|
||||
{
|
||||
Flag_None = 0,
|
||||
Flag_TruncateToPrecision = 1<<0, // truncate length to stream precision()
|
||||
Flag_SpacePadPositive = 1<<1, // pad positive values with spaces
|
||||
Flag_VariableWidth = 1<<2, // variable field width in arg list
|
||||
Flag_VariablePrecision = 1<<3 // variable field precision in arg list
|
||||
};
|
||||
FormatArg()
|
||||
: m_value(nullptr),
|
||||
m_formatImpl(nullptr),
|
||||
m_toIntImpl(nullptr)
|
||||
{ }
|
||||
|
||||
// out is the output stream, fmt is the full format string
|
||||
FormatIterator(std::ostream& out, const char* fmt)
|
||||
: m_out(out),
|
||||
m_fmt(fmt),
|
||||
m_extraFlags(Flag_None),
|
||||
m_wantWidth(false),
|
||||
m_wantPrecision(false),
|
||||
m_variableWidth(0),
|
||||
m_variablePrecision(0),
|
||||
m_origWidth(out.width()),
|
||||
m_origPrecision(out.precision()),
|
||||
m_origFlags(out.flags()),
|
||||
m_origFill(out.fill())
|
||||
template<typename T>
|
||||
explicit FormatArg(const T& value)
|
||||
: m_value(static_cast<const void*>(&value)),
|
||||
m_formatImpl(&formatImpl<T>),
|
||||
m_toIntImpl(&toIntImpl<T>)
|
||||
{ }
|
||||
|
||||
// Print remaining part of format string.
|
||||
void finish()
|
||||
void format(std::ostream& out, const char* fmtBegin,
|
||||
const char* fmtEnd, int ntrunc) const
|
||||
{
|
||||
// It would be nice if we could do this from the destructor, but we
|
||||
// can't if TINFORMAT_ERROR is used to throw an exception!
|
||||
m_fmt = printFormatStringLiteral(m_out, m_fmt);
|
||||
if(*m_fmt != '\0')
|
||||
TINYFORMAT_ERROR("tinyformat: Too many conversion specifiers in format string");
|
||||
assert(m_value);
|
||||
assert(m_formatImpl);
|
||||
m_formatImpl(out, fmtBegin, fmtEnd, ntrunc, m_value);
|
||||
}
|
||||
|
||||
~FormatIterator()
|
||||
int toInt() const
|
||||
{
|
||||
// Restore stream state
|
||||
m_out.width(m_origWidth);
|
||||
m_out.precision(m_origPrecision);
|
||||
m_out.flags(m_origFlags);
|
||||
m_out.fill(m_origFill);
|
||||
assert(m_value);
|
||||
assert(m_toIntImpl);
|
||||
return m_toIntImpl(m_value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void accept(const T& value);
|
||||
|
||||
private:
|
||||
// Parse and return an integer from the string c, as atoi()
|
||||
// On return, c is set to one past the end of the integer.
|
||||
static int parseIntAndAdvance(const char*& c)
|
||||
{
|
||||
int i = 0;
|
||||
for(;*c >= '0' && *c <= '9'; ++c)
|
||||
i = 10*i + (*c - '0');
|
||||
return i;
|
||||
}
|
||||
|
||||
// Format at most truncLen characters of a C string to the given
|
||||
// stream. Return true if formatting proceeded (generic version always
|
||||
// returns false)
|
||||
template<typename T>
|
||||
static bool formatCStringTruncate(std::ostream& /*out*/, const T& /*value*/,
|
||||
std::streamsize /*truncLen*/)
|
||||
TINYFORMAT_HIDDEN static void formatImpl(std::ostream& out, const char* fmtBegin,
|
||||
const char* fmtEnd, int ntrunc, const void* value)
|
||||
{
|
||||
return false;
|
||||
formatValue(out, fmtBegin, fmtEnd, ntrunc, *static_cast<const T*>(value));
|
||||
}
|
||||
# define TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE(type) \
|
||||
static bool formatCStringTruncate(std::ostream& out, type* value, \
|
||||
std::streamsize truncLen) \
|
||||
{ \
|
||||
std::streamsize len = 0; \
|
||||
while(len < truncLen && value[len] != 0) \
|
||||
++len; \
|
||||
out.write(value, len); \
|
||||
return true; \
|
||||
}
|
||||
// Overload for const char* and char*. Could overload for signed &
|
||||
// unsigned char too, but these are technically unneeded for printf
|
||||
// compatibility.
|
||||
TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE(const char)
|
||||
TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE(char)
|
||||
# undef TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE
|
||||
|
||||
// Print literal part of format string and return next format spec
|
||||
// position.
|
||||
//
|
||||
// Skips over any occurrences of '%%', printing a literal '%' to the
|
||||
// output. The position of the first % character of the next
|
||||
// nontrivial format spec is returned, or the end of string.
|
||||
static const char* printFormatStringLiteral(std::ostream& out,
|
||||
const char* fmt)
|
||||
template<typename T>
|
||||
TINYFORMAT_HIDDEN static int toIntImpl(const void* value)
|
||||
{
|
||||
const char* c = fmt;
|
||||
for(; true; ++c)
|
||||
{
|
||||
switch(*c)
|
||||
{
|
||||
case '\0':
|
||||
out.write(fmt, static_cast<std::streamsize>(c - fmt));
|
||||
return c;
|
||||
case '%':
|
||||
out.write(fmt, static_cast<std::streamsize>(c - fmt));
|
||||
if(*(c+1) != '%')
|
||||
return c;
|
||||
// for "%%", tack trailing % onto next literal section.
|
||||
fmt = ++c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return convertToInt<T>::invoke(*static_cast<const T*>(value));
|
||||
}
|
||||
|
||||
static const char* streamStateFromFormat(std::ostream& out,
|
||||
unsigned int& extraFlags,
|
||||
const char* fmtStart,
|
||||
int variableWidth,
|
||||
int variablePrecision);
|
||||
|
||||
// Private copy & assign: Kill gcc warnings with -Weffc++
|
||||
FormatIterator(const FormatIterator&);
|
||||
FormatIterator& operator=(const FormatIterator&);
|
||||
|
||||
// Stream, current format string & state
|
||||
std::ostream& m_out;
|
||||
const char* m_fmt;
|
||||
unsigned int m_extraFlags;
|
||||
// State machine info for handling of variable width & precision
|
||||
bool m_wantWidth;
|
||||
bool m_wantPrecision;
|
||||
int m_variableWidth;
|
||||
int m_variablePrecision;
|
||||
// Saved stream state
|
||||
std::streamsize m_origWidth;
|
||||
std::streamsize m_origPrecision;
|
||||
std::ios::fmtflags m_origFlags;
|
||||
char m_origFill;
|
||||
const void* m_value;
|
||||
void (*m_formatImpl)(std::ostream& out, const char* fmtBegin,
|
||||
const char* fmtEnd, int ntrunc, const void* value);
|
||||
int (*m_toIntImpl)(const void* value);
|
||||
};
|
||||
|
||||
|
||||
// Accept a value for formatting into the internal stream.
|
||||
template<typename T>
|
||||
TINYFORMAT_NOINLINE // < greatly reduces bloat in optimized builds
|
||||
void FormatIterator::accept(const T& value)
|
||||
// Parse and return an integer from the string c, as atoi()
|
||||
// On return, c is set to one past the end of the integer.
|
||||
inline int parseIntAndAdvance(const char*& c)
|
||||
{
|
||||
// Parse the format string
|
||||
const char* fmtEnd = 0;
|
||||
if(m_extraFlags == Flag_None && !m_wantWidth && !m_wantPrecision)
|
||||
{
|
||||
m_fmt = printFormatStringLiteral(m_out, m_fmt);
|
||||
fmtEnd = streamStateFromFormat(m_out, m_extraFlags, m_fmt, 0, 0);
|
||||
m_wantWidth = (m_extraFlags & Flag_VariableWidth) != 0;
|
||||
m_wantPrecision = (m_extraFlags & Flag_VariablePrecision) != 0;
|
||||
}
|
||||
// Consume value as variable width and precision specifier if necessary
|
||||
if(m_extraFlags & (Flag_VariableWidth | Flag_VariablePrecision))
|
||||
{
|
||||
if(m_wantWidth || m_wantPrecision)
|
||||
{
|
||||
int v = convertToInt<T>::invoke(value);
|
||||
if(m_wantWidth)
|
||||
{
|
||||
m_variableWidth = v;
|
||||
m_wantWidth = false;
|
||||
}
|
||||
else if(m_wantPrecision)
|
||||
{
|
||||
m_variablePrecision = v;
|
||||
m_wantPrecision = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// If we get here, we've set both the variable precision and width as
|
||||
// required and we need to rerun the stream state setup to insert these.
|
||||
fmtEnd = streamStateFromFormat(m_out, m_extraFlags, m_fmt,
|
||||
m_variableWidth, m_variablePrecision);
|
||||
}
|
||||
int i = 0;
|
||||
for(;*c >= '0' && *c <= '9'; ++c)
|
||||
i = 10*i + (*c - '0');
|
||||
return i;
|
||||
}
|
||||
|
||||
// Format the value into the stream.
|
||||
if(!(m_extraFlags & (Flag_SpacePadPositive | Flag_TruncateToPrecision)))
|
||||
formatValue(m_out, m_fmt, fmtEnd, value);
|
||||
else
|
||||
// Print literal part of format string and return next format spec
|
||||
// position.
|
||||
//
|
||||
// Skips over any occurrences of '%%', printing a literal '%' to the
|
||||
// output. The position of the first % character of the next
|
||||
// nontrivial format spec is returned, or the end of string.
|
||||
inline const char* printFormatStringLiteral(std::ostream& out, const char* fmt)
|
||||
{
|
||||
const char* c = fmt;
|
||||
for(;; ++c)
|
||||
{
|
||||
// The following are special cases where there's no direct
|
||||
// correspondence between stream formatting and the printf() behaviour.
|
||||
// Instead, we simulate the behaviour crudely by formatting into a
|
||||
// temporary string stream and munging the resulting string.
|
||||
std::ostringstream tmpStream;
|
||||
tmpStream.copyfmt(m_out);
|
||||
if(m_extraFlags & Flag_SpacePadPositive)
|
||||
tmpStream.setf(std::ios::showpos);
|
||||
// formatCStringTruncate is required for truncating conversions like
|
||||
// "%.4s" where at most 4 characters of the c-string should be read.
|
||||
// If we didn't include this special case, we might read off the end.
|
||||
if(!( (m_extraFlags & Flag_TruncateToPrecision) &&
|
||||
formatCStringTruncate(tmpStream, value, m_out.precision()) ))
|
||||
switch(*c)
|
||||
{
|
||||
// Not a truncated c-string; just format normally.
|
||||
formatValue(tmpStream, m_fmt, fmtEnd, value);
|
||||
case '\0':
|
||||
out.write(fmt, c - fmt);
|
||||
return c;
|
||||
case '%':
|
||||
out.write(fmt, c - fmt);
|
||||
if(*(c+1) != '%')
|
||||
return c;
|
||||
// for "%%", tack trailing % onto next literal section.
|
||||
fmt = ++c;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
std::string result = tmpStream.str(); // allocates... yuck.
|
||||
if(m_extraFlags & Flag_SpacePadPositive)
|
||||
{
|
||||
for(size_t i = 0, iend = result.size(); i < iend; ++i)
|
||||
if(result[i] == '+')
|
||||
result[i] = ' ';
|
||||
}
|
||||
if((m_extraFlags & Flag_TruncateToPrecision) &&
|
||||
(int)result.size() > (int)m_out.precision())
|
||||
m_out.write(result.c_str(), m_out.precision());
|
||||
else
|
||||
m_out << result;
|
||||
}
|
||||
m_extraFlags = Flag_None;
|
||||
m_fmt = fmtEnd;
|
||||
}
|
||||
|
||||
|
||||
@@ -686,13 +590,14 @@ void FormatIterator::accept(const T& value)
|
||||
// with the form "%[flags][width][.precision][length]type".
|
||||
//
|
||||
// Formatting options which can't be natively represented using the ostream
|
||||
// state are returned in the extraFlags parameter which is a bitwise
|
||||
// combination of values from the ExtraFormatFlags enum.
|
||||
inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
|
||||
unsigned int& extraFlags,
|
||||
const char* fmtStart,
|
||||
int variableWidth,
|
||||
int variablePrecision)
|
||||
// state are returned in spacePadPositive (for space padded positive numbers)
|
||||
// and ntrunc (for truncating conversions). argIndex is incremented if
|
||||
// necessary to pull out variable width and precision. The function returns a
|
||||
// pointer to the character after the end of the current format spec.
|
||||
inline const char* streamStateFromFormat(std::ostream& out, bool& spacePadPositive,
|
||||
int& ntrunc, const char* fmtStart,
|
||||
const detail::FormatArg* formatters,
|
||||
int& argIndex, int numFormatters)
|
||||
{
|
||||
if(*fmtStart != '%')
|
||||
{
|
||||
@@ -707,9 +612,9 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
|
||||
out.unsetf(std::ios::adjustfield | std::ios::basefield |
|
||||
std::ios::floatfield | std::ios::showbase | std::ios::boolalpha |
|
||||
std::ios::showpoint | std::ios::showpos | std::ios::uppercase);
|
||||
extraFlags = Flag_None;
|
||||
bool precisionSet = false;
|
||||
bool widthSet = false;
|
||||
int widthExtra = 0;
|
||||
const char* c = fmtStart + 1;
|
||||
// 1) Parse flags
|
||||
for(;; ++c)
|
||||
@@ -736,12 +641,15 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
|
||||
case ' ':
|
||||
// overridden by show positive sign, '+' flag.
|
||||
if(!(out.flags() & std::ios::showpos))
|
||||
extraFlags |= Flag_SpacePadPositive;
|
||||
spacePadPositive = true;
|
||||
continue;
|
||||
case '+':
|
||||
out.setf(std::ios::showpos);
|
||||
extraFlags &= ~Flag_SpacePadPositive;
|
||||
spacePadPositive = false;
|
||||
widthExtra = 1;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -754,15 +662,19 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
|
||||
if(*c == '*')
|
||||
{
|
||||
widthSet = true;
|
||||
if(variableWidth < 0)
|
||||
int width = 0;
|
||||
if(argIndex < numFormatters)
|
||||
width = formatters[argIndex++].toInt();
|
||||
else
|
||||
TINYFORMAT_ERROR("tinyformat: Not enough arguments to read variable width");
|
||||
if(width < 0)
|
||||
{
|
||||
// negative widths correspond to '-' flag set
|
||||
out.fill(' ');
|
||||
out.setf(std::ios::left, std::ios::adjustfield);
|
||||
variableWidth = -variableWidth;
|
||||
width = -width;
|
||||
}
|
||||
out.width(variableWidth);
|
||||
extraFlags |= Flag_VariableWidth;
|
||||
out.width(width);
|
||||
++c;
|
||||
}
|
||||
// 3) Parse precision
|
||||
@@ -773,8 +685,10 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
|
||||
if(*c == '*')
|
||||
{
|
||||
++c;
|
||||
extraFlags |= Flag_VariablePrecision;
|
||||
precision = variablePrecision;
|
||||
if(argIndex < numFormatters)
|
||||
precision = formatters[argIndex++].toInt();
|
||||
else
|
||||
TINYFORMAT_ERROR("tinyformat: Not enough arguments to read variable precision");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -806,23 +720,27 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
|
||||
break;
|
||||
case 'X':
|
||||
out.setf(std::ios::uppercase);
|
||||
// Falls through
|
||||
case 'x': case 'p':
|
||||
out.setf(std::ios::hex, std::ios::basefield);
|
||||
intConversion = true;
|
||||
break;
|
||||
case 'E':
|
||||
out.setf(std::ios::uppercase);
|
||||
// Falls through
|
||||
case 'e':
|
||||
out.setf(std::ios::scientific, std::ios::floatfield);
|
||||
out.setf(std::ios::dec, std::ios::basefield);
|
||||
break;
|
||||
case 'F':
|
||||
out.setf(std::ios::uppercase);
|
||||
// Falls through
|
||||
case 'f':
|
||||
out.setf(std::ios::fixed, std::ios::floatfield);
|
||||
break;
|
||||
case 'G':
|
||||
out.setf(std::ios::uppercase);
|
||||
// Falls through
|
||||
case 'g':
|
||||
out.setf(std::ios::dec, std::ios::basefield);
|
||||
// As in boost::format, let stream decide float format.
|
||||
@@ -837,7 +755,7 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
|
||||
break;
|
||||
case 's':
|
||||
if(precisionSet)
|
||||
extraFlags |= Flag_TruncateToPrecision;
|
||||
ntrunc = static_cast<int>(out.precision());
|
||||
// Make %s print booleans as "true" and "false"
|
||||
out.setf(std::ios::boolalpha);
|
||||
break;
|
||||
@@ -849,6 +767,8 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
|
||||
TINYFORMAT_ERROR("tinyformat: Conversion spec incorrectly "
|
||||
"terminated by end of string");
|
||||
return c;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(intConversion && precisionSet && !widthSet)
|
||||
{
|
||||
@@ -856,7 +776,7 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
|
||||
// padded with zeros on the left). This isn't really supported by the
|
||||
// iostreams, but we can approximately simulate it with the width if
|
||||
// the width isn't otherwise used.
|
||||
out.width(out.precision());
|
||||
out.width(out.precision() + widthExtra);
|
||||
out.setf(std::ios::internal, std::ios::adjustfield);
|
||||
out.fill('0');
|
||||
}
|
||||
@@ -865,119 +785,266 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private format function on top of which the public interface is implemented.
|
||||
// We enforce a mimimum of one value to be formatted to prevent bugs looking like
|
||||
//
|
||||
// const char* myStr = "100% broken";
|
||||
// printf(myStr); // Parses % as a format specifier
|
||||
inline void formatImpl(std::ostream& out, const char* fmt,
|
||||
const detail::FormatArg* formatters,
|
||||
int numFormatters)
|
||||
{
|
||||
// Saved stream state
|
||||
std::streamsize origWidth = out.width();
|
||||
std::streamsize origPrecision = out.precision();
|
||||
std::ios::fmtflags origFlags = out.flags();
|
||||
char origFill = out.fill();
|
||||
|
||||
for (int argIndex = 0; argIndex < numFormatters; ++argIndex)
|
||||
{
|
||||
// Parse the format string
|
||||
fmt = printFormatStringLiteral(out, fmt);
|
||||
bool spacePadPositive = false;
|
||||
int ntrunc = -1;
|
||||
const char* fmtEnd = streamStateFromFormat(out, spacePadPositive, ntrunc, fmt,
|
||||
formatters, argIndex, numFormatters);
|
||||
if (argIndex >= numFormatters)
|
||||
{
|
||||
// Check args remain after reading any variable width/precision
|
||||
TINYFORMAT_ERROR("tinyformat: Not enough format arguments");
|
||||
return;
|
||||
}
|
||||
const FormatArg& arg = formatters[argIndex];
|
||||
// Format the arg into the stream.
|
||||
if(!spacePadPositive)
|
||||
arg.format(out, fmt, fmtEnd, ntrunc);
|
||||
else
|
||||
{
|
||||
// The following is a special case with no direct correspondence
|
||||
// between stream formatting and the printf() behaviour. Simulate
|
||||
// it crudely by formatting into a temporary string stream and
|
||||
// munging the resulting string.
|
||||
std::ostringstream tmpStream;
|
||||
tmpStream.copyfmt(out);
|
||||
tmpStream.setf(std::ios::showpos);
|
||||
arg.format(tmpStream, fmt, fmtEnd, ntrunc);
|
||||
std::string result = tmpStream.str(); // allocates... yuck.
|
||||
for(size_t i = 0, iend = result.size(); i < iend; ++i)
|
||||
if(result[i] == '+') result[i] = ' ';
|
||||
out << result;
|
||||
}
|
||||
fmt = fmtEnd;
|
||||
}
|
||||
|
||||
// Print remaining part of format string.
|
||||
fmt = printFormatStringLiteral(out, fmt);
|
||||
if(*fmt != '\0')
|
||||
TINYFORMAT_ERROR("tinyformat: Too many conversion specifiers in format string");
|
||||
|
||||
// Restore stream state
|
||||
out.width(origWidth);
|
||||
out.precision(origPrecision);
|
||||
out.flags(origFlags);
|
||||
out.fill(origFill);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
/// List of template arguments format(), held in a type-opaque way.
|
||||
///
|
||||
/// A const reference to FormatList (typedef'd as FormatListRef) may be
|
||||
/// conveniently used to pass arguments to non-template functions: All type
|
||||
/// information has been stripped from the arguments, leaving just enough of a
|
||||
/// common interface to perform formatting as required.
|
||||
class FormatList
|
||||
{
|
||||
public:
|
||||
FormatList(detail::FormatArg* formatters, int N)
|
||||
: m_formatters(formatters), m_N(N) { }
|
||||
|
||||
friend void vformat(std::ostream& out, const char* fmt,
|
||||
const FormatList& list);
|
||||
|
||||
private:
|
||||
const detail::FormatArg* m_formatters;
|
||||
int m_N;
|
||||
};
|
||||
|
||||
/// Reference to type-opaque format list for passing to vformat()
|
||||
typedef const FormatList& FormatListRef;
|
||||
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Format list subclass with fixed storage to avoid dynamic allocation
|
||||
template<int N>
|
||||
class FormatListN : public FormatList
|
||||
{
|
||||
public:
|
||||
#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
|
||||
template<typename... Args>
|
||||
explicit FormatListN(const Args&... args)
|
||||
: FormatList(&m_formatterStore[0], N),
|
||||
m_formatterStore { FormatArg(args)... }
|
||||
{ static_assert(sizeof...(args) == N, "Number of args must be N"); }
|
||||
#else // C++98 version
|
||||
void init(int) {}
|
||||
# define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \
|
||||
\
|
||||
template<TINYFORMAT_ARGTYPES(n)> \
|
||||
explicit FormatListN(TINYFORMAT_VARARGS(n)) \
|
||||
: FormatList(&m_formatterStore[0], n) \
|
||||
{ assert(n == N); init(0, TINYFORMAT_PASSARGS(n)); } \
|
||||
\
|
||||
template<TINYFORMAT_ARGTYPES(n)> \
|
||||
void init(int i, TINYFORMAT_VARARGS(n)) \
|
||||
{ \
|
||||
m_formatterStore[i] = FormatArg(v1); \
|
||||
init(i+1 TINYFORMAT_PASSARGS_TAIL(n)); \
|
||||
}
|
||||
|
||||
template<typename T1>
|
||||
void format(FormatIterator& fmtIter, const T1& value1)
|
||||
TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR)
|
||||
# undef TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR
|
||||
#endif
|
||||
|
||||
private:
|
||||
FormatArg m_formatterStore[N];
|
||||
};
|
||||
|
||||
// Special 0-arg version - MSVC says zero-sized C array in struct is nonstandard
|
||||
template<> class FormatListN<0> : public FormatList
|
||||
{
|
||||
fmtIter.accept(value1);
|
||||
fmtIter.finish();
|
||||
}
|
||||
|
||||
// General version for C++11
|
||||
template<typename T1, typename... Args>
|
||||
void format(FormatIterator& fmtIter, const T1& value1, const Args&... args)
|
||||
{
|
||||
fmtIter.accept(value1);
|
||||
format(fmtIter, args...);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline void format(FormatIterator& fmtIter)
|
||||
{
|
||||
fmtIter.finish();
|
||||
}
|
||||
|
||||
// General version for C++98
|
||||
#define TINYFORMAT_MAKE_FORMAT_DETAIL(n) \
|
||||
template<TINYFORMAT_ARGTYPES(n)> \
|
||||
void format(detail::FormatIterator& fmtIter, TINYFORMAT_VARARGS(n)) \
|
||||
{ \
|
||||
fmtIter.accept(v1); \
|
||||
format(fmtIter TINYFORMAT_PASSARGS_TAIL(n)); \
|
||||
}
|
||||
|
||||
TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMAT_DETAIL)
|
||||
#undef TINYFORMAT_MAKE_FORMAT_DETAIL
|
||||
|
||||
#endif // End C++98 variadic template emulation for format()
|
||||
public: FormatListN() : FormatList(0, 0) {}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Implement all the main interface functions here in terms of detail::format()
|
||||
// Primary API functions
|
||||
|
||||
#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
|
||||
|
||||
// C++11 - the simple case
|
||||
template<typename T1, typename... Args>
|
||||
void format(std::ostream& out, const char* fmt, const T1& v1, const Args&... args)
|
||||
/// Make type-agnostic format list from list of template arguments.
|
||||
///
|
||||
/// The exact return type of this function is an implementation detail and
|
||||
/// shouldn't be relied upon. Instead it should be stored as a FormatListRef:
|
||||
///
|
||||
/// FormatListRef formatList = makeFormatList( /*...*/ );
|
||||
template<typename... Args>
|
||||
detail::FormatListN<sizeof...(Args)> makeFormatList(const Args&... args)
|
||||
{
|
||||
detail::FormatIterator fmtIter(out, fmt);
|
||||
format(fmtIter, v1, args...);
|
||||
return detail::FormatListN<sizeof...(args)>(args...);
|
||||
}
|
||||
|
||||
template<typename T1, typename... Args>
|
||||
std::string format(const char* fmt, const T1& v1, const Args&... args)
|
||||
#else // C++98 version
|
||||
|
||||
inline detail::FormatListN<0> makeFormatList()
|
||||
{
|
||||
return detail::FormatListN<0>();
|
||||
}
|
||||
#define TINYFORMAT_MAKE_MAKEFORMATLIST(n) \
|
||||
template<TINYFORMAT_ARGTYPES(n)> \
|
||||
detail::FormatListN<n> makeFormatList(TINYFORMAT_VARARGS(n)) \
|
||||
{ \
|
||||
return detail::FormatListN<n>(TINYFORMAT_PASSARGS(n)); \
|
||||
}
|
||||
TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_MAKEFORMATLIST)
|
||||
#undef TINYFORMAT_MAKE_MAKEFORMATLIST
|
||||
|
||||
#endif
|
||||
|
||||
/// Format list of arguments to the stream according to the given format string.
|
||||
///
|
||||
/// The name vformat() is chosen for the semantic similarity to vprintf(): the
|
||||
/// list of format arguments is held in a single function argument.
|
||||
inline void vformat(std::ostream& out, const char* fmt, FormatListRef list)
|
||||
{
|
||||
detail::formatImpl(out, fmt, list.m_formatters, list.m_N);
|
||||
}
|
||||
|
||||
|
||||
#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
|
||||
|
||||
/// Format list of arguments to the stream according to given format string.
|
||||
template<typename... Args>
|
||||
void format(std::ostream& out, const char* fmt, const Args&... args)
|
||||
{
|
||||
vformat(out, fmt, makeFormatList(args...));
|
||||
}
|
||||
|
||||
/// Format list of arguments according to the given format string and return
|
||||
/// the result as a string.
|
||||
template<typename... Args>
|
||||
std::string format(const char* fmt, const Args&... args)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
format(oss, fmt, v1, args...);
|
||||
format(oss, fmt, args...);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
template<typename T1, typename... Args>
|
||||
std::string format(const std::string &fmt, const T1& v1, const Args&... args)
|
||||
/// Format list of arguments to std::cout, according to the given format string
|
||||
template<typename... Args>
|
||||
void printf(const char* fmt, const Args&... args)
|
||||
{
|
||||
format(std::cout, fmt, args...);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void printfln(const char* fmt, const Args&... args)
|
||||
{
|
||||
format(std::cout, fmt, args...);
|
||||
std::cout << '\n';
|
||||
}
|
||||
|
||||
#else // C++98 version
|
||||
|
||||
inline void format(std::ostream& out, const char* fmt)
|
||||
{
|
||||
vformat(out, fmt, makeFormatList());
|
||||
}
|
||||
|
||||
inline std::string format(const char* fmt)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
format(oss, fmt.c_str(), v1, args...);
|
||||
format(oss, fmt);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
template<typename T1, typename... Args>
|
||||
void printf(const char* fmt, const T1& v1, const Args&... args)
|
||||
inline void printf(const char* fmt)
|
||||
{
|
||||
format(std::cout, fmt, v1, args...);
|
||||
format(std::cout, fmt);
|
||||
}
|
||||
|
||||
#else
|
||||
inline void printfln(const char* fmt)
|
||||
{
|
||||
format(std::cout, fmt);
|
||||
std::cout << '\n';
|
||||
}
|
||||
|
||||
// C++98 - define the interface functions using the wrapping macros
|
||||
#define TINYFORMAT_MAKE_FORMAT_FUNCS(n) \
|
||||
\
|
||||
template<TINYFORMAT_ARGTYPES(n)> \
|
||||
void format(std::ostream& out, const char* fmt, TINYFORMAT_VARARGS(n)) \
|
||||
{ \
|
||||
tinyformat::detail::FormatIterator fmtIter(out, fmt); \
|
||||
tinyformat::detail::format(fmtIter, TINYFORMAT_PASSARGS(n)); \
|
||||
vformat(out, fmt, makeFormatList(TINYFORMAT_PASSARGS(n))); \
|
||||
} \
|
||||
\
|
||||
template<TINYFORMAT_ARGTYPES(n)> \
|
||||
std::string format(const char* fmt, TINYFORMAT_VARARGS(n)) \
|
||||
{ \
|
||||
std::ostringstream oss; \
|
||||
tinyformat::format(oss, fmt, TINYFORMAT_PASSARGS(n)); \
|
||||
return oss.str(); \
|
||||
} \
|
||||
\
|
||||
template<TINYFORMAT_ARGTYPES(n)> \
|
||||
std::string format(const std::string &fmt, TINYFORMAT_VARARGS(n)) \
|
||||
{ \
|
||||
std::ostringstream oss; \
|
||||
tinyformat::format(oss, fmt.c_str(), TINYFORMAT_PASSARGS(n)); \
|
||||
format(oss, fmt, TINYFORMAT_PASSARGS(n)); \
|
||||
return oss.str(); \
|
||||
} \
|
||||
\
|
||||
template<TINYFORMAT_ARGTYPES(n)> \
|
||||
void printf(const char* fmt, TINYFORMAT_VARARGS(n)) \
|
||||
{ \
|
||||
tinyformat::format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
|
||||
format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
|
||||
} \
|
||||
\
|
||||
template<TINYFORMAT_ARGTYPES(n)> \
|
||||
void printfln(const char* fmt, TINYFORMAT_VARARGS(n)) \
|
||||
{ \
|
||||
format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
|
||||
std::cout << '\n'; \
|
||||
}
|
||||
|
||||
TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMAT_FUNCS)
|
||||
@@ -985,49 +1052,14 @@ TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMAT_FUNCS)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Define deprecated wrapping macro for backward compatibility in tinyformat
|
||||
// 1.x. Will be removed in version 2!
|
||||
#define TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS
|
||||
#define TINYFORMAT_WRAP_FORMAT_N(n, returnType, funcName, funcDeclSuffix, \
|
||||
bodyPrefix, streamName, bodySuffix) \
|
||||
template<TINYFORMAT_ARGTYPES(n)> \
|
||||
returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt, \
|
||||
TINYFORMAT_VARARGS(n)) funcDeclSuffix \
|
||||
{ \
|
||||
bodyPrefix \
|
||||
tinyformat::format(streamName, fmt, TINYFORMAT_PASSARGS(n)); \
|
||||
bodySuffix \
|
||||
} \
|
||||
|
||||
#define TINYFORMAT_WRAP_FORMAT(returnType, funcName, funcDeclSuffix, \
|
||||
bodyPrefix, streamName, bodySuffix) \
|
||||
inline \
|
||||
returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt \
|
||||
) funcDeclSuffix \
|
||||
{ \
|
||||
bodyPrefix \
|
||||
tinyformat::detail::FormatIterator(streamName, fmt).finish(); \
|
||||
bodySuffix \
|
||||
} \
|
||||
TINYFORMAT_WRAP_FORMAT_N(1 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
|
||||
TINYFORMAT_WRAP_FORMAT_N(2 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
|
||||
TINYFORMAT_WRAP_FORMAT_N(3 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
|
||||
TINYFORMAT_WRAP_FORMAT_N(4 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
|
||||
TINYFORMAT_WRAP_FORMAT_N(5 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
|
||||
TINYFORMAT_WRAP_FORMAT_N(6 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
|
||||
TINYFORMAT_WRAP_FORMAT_N(7 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
|
||||
TINYFORMAT_WRAP_FORMAT_N(8 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
|
||||
TINYFORMAT_WRAP_FORMAT_N(9 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
|
||||
TINYFORMAT_WRAP_FORMAT_N(10, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
|
||||
TINYFORMAT_WRAP_FORMAT_N(11, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
|
||||
TINYFORMAT_WRAP_FORMAT_N(12, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
|
||||
TINYFORMAT_WRAP_FORMAT_N(13, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
|
||||
TINYFORMAT_WRAP_FORMAT_N(14, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
|
||||
TINYFORMAT_WRAP_FORMAT_N(15, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
|
||||
TINYFORMAT_WRAP_FORMAT_N(16, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
|
||||
|
||||
// Added for Bitcoin Core
|
||||
template<typename... Args>
|
||||
std::string format(const std::string &fmt, const Args&... args)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
format(oss, fmt.c_str(), args...);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
} // namespace tinyformat
|
||||
|
||||
|
||||
Reference in New Issue
Block a user