diff --git a/src/.clang-format b/src/.clang-format --- a/src/.clang-format +++ b/src/.clang-format @@ -11,5 +11,4 @@ ReflowComments: true AllowShortIfStatementsOnASingleLine: true AllowShortFunctionsOnASingleLine: Inline -ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH, BOOST_REVERSE_FOREACH ] CommentPragmas: '@DISABLE FORMATING FOR THIS COMMENT@' diff --git a/src/Makefile.am b/src/Makefile.am --- a/src/Makefile.am +++ b/src/Makefile.am @@ -159,6 +159,7 @@ pow.h \ protocol.h \ random.h \ + reverse_iterator.h \ reverselock.h \ rpc/blockchain.h \ rpc/client.h \ diff --git a/src/avalanche.cpp b/src/avalanche.cpp --- a/src/avalanche.cpp +++ b/src/avalanche.cpp @@ -7,11 +7,10 @@ #include "chain.h" #include "config/bitcoin-config.h" #include "netmessagemaker.h" +#include "reverse_iterator.h" #include "scheduler.h" #include "validation.h" -#include - #include static uint32_t countBits(uint32_t v) { @@ -315,7 +314,7 @@ auto r = vote_records.getReadView(); for (const std::pair &p : - boost::adaptors::reverse(r)) { + reverse_iterate(r)) { const CBlockIndex *pindex = p.first; if (!IsWorthPolling(pindex)) { // Obviously do not poll if the block is not worth polling. diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -6,11 +6,10 @@ #include "chain.h" #include "chainparams.h" +#include "reverse_iterator.h" #include -#include - namespace Checkpoints { bool CheckBlock(const CCheckpointData &data, int nHeight, const uint256 &hash) { @@ -26,8 +25,7 @@ CBlockIndex *GetLastCheckpoint(const CCheckpointData &data) { const MapCheckpoints &checkpoints = data.mapCheckpoints; - for (const MapCheckpoints::value_type &i : - boost::adaptors::reverse(checkpoints)) { + for (const MapCheckpoints::value_type &i : reverse_iterate(checkpoints)) { const uint256 &hash = i.second; BlockMap::const_iterator t = mapBlockIndex.find(hash); if (t != mapBlockIndex.end()) { diff --git a/src/net_processing.cpp b/src/net_processing.cpp --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -23,6 +23,7 @@ #include "primitives/block.h" #include "primitives/transaction.h" #include "random.h" +#include "reverse_iterator.h" #include "scheduler.h" #include "tinyformat.h" #include "txmempool.h" @@ -33,8 +34,6 @@ #include "validation.h" #include "validationinterface.h" -#include - #if defined(NDEBUG) #error "Bitcoin cannot be compiled without assertions." #endif @@ -1067,7 +1066,7 @@ if (nNewHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 0)) { - for (const uint256 &hash : boost::adaptors::reverse(vHashes)) { + for (const uint256 &hash : reverse_iterate(vHashes)) { pnode->PushBlockHash(hash); } } @@ -1651,8 +1650,7 @@ } else { std::vector vGetData; // Download as much as possible, from earliest to latest. - for (const CBlockIndex *pindex : - boost::adaptors::reverse(vToFetch)) { + for (const CBlockIndex *pindex : reverse_iterate(vToFetch)) { if (nodestate->nBlocksInFlight >= MAX_BLOCKS_IN_TRANSIT_PER_PEER) { // Can't download any more from this peer diff --git a/src/reverse_iterator.h b/src/reverse_iterator.h new file mode 100644 --- /dev/null +++ b/src/reverse_iterator.h @@ -0,0 +1,29 @@ +// Taken from https://gist.github.com/arvidsson/7231973 + +#ifndef BITCOIN_REVERSE_ITERATOR_HPP +#define BITCOIN_REVERSE_ITERATOR_HPP + +/** + * Template used for reverse iteration in C++11 range-based for loops. + * + * std::vector v = {1, 2, 3, 4, 5}; + * for (auto x : reverse_iterate(v)) + * std::cout << x << " "; + */ + +template class reverse_range { + T &x; + +public: + reverse_range(T &xin) : x(xin) {} + + auto begin() const -> decltype(this->x.rbegin()) { return x.rbegin(); } + + auto end() const -> decltype(this->x.rend()) { return x.rend(); } +}; + +template reverse_range reverse_iterate(T &x) { + return reverse_range(x); +} + +#endif // BITCOIN_REVERSE_ITERATOR_HPP diff --git a/src/rwcollection.h b/src/rwcollection.h --- a/src/rwcollection.h +++ b/src/rwcollection.h @@ -37,10 +37,18 @@ typedef typename boost::range_iterator::type iterator; iterator begin() { return std::begin(*collection); } iterator end() { return std::end(*collection); } + std::reverse_iterator rbegin() { return collection->rbegin(); } + std::reverse_iterator rend() { return collection->rend(); } typedef typename boost::range_iterator::type const_iterator; const_iterator begin() const { return std::begin(*collection); } const_iterator end() const { return std::end(*collection); } + std::reverse_iterator rbegin() const { + return collection->rbegin(); + } + std::reverse_iterator rend() const { + return collection->rend(); + } /** * Forward bracket operator. diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -5,12 +5,12 @@ #include "prevector.h" #include +#include "reverse_iterator.h" #include "serialize.h" #include "streams.h" #include "test/test_bitcoin.h" -#include #include BOOST_FIXTURE_TEST_SUITE(prevector_tests, TestingSetup) @@ -53,15 +53,13 @@ for (const T &v : pre_vector) { local_check(v == real_vector[pos++]); } - // FIXME: For some reason, the prevector iterrator doesn't conform to - // what boost::adaptors::reverse expect. - for (const T &v : boost::adaptors::reverse(pre_vector)) { + for (const T &v : reverse_iterate(pre_vector)) { local_check(v == real_vector[--pos]); } for (const T &v : const_pre_vector) { local_check(v == real_vector[pos++]); } - for (const T &v : boost::adaptors::reverse(const_pre_vector)) { + for (const T &v : reverse_iterate(const_pre_vector)) { local_check(v == real_vector[--pos]); } CDataStream ss1(SER_DISK, 0); diff --git a/src/test/rwcollection_tests.cpp b/src/test/rwcollection_tests.cpp --- a/src/test/rwcollection_tests.cpp +++ b/src/test/rwcollection_tests.cpp @@ -2,11 +2,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "reverse_iterator.h" #include "rwcollection.h" #include "test/test_bitcoin.h" -#include #include #include @@ -36,7 +36,7 @@ } e = 0; - for (int &i : boost::adaptors::reverse(w)) { + for (int &i : reverse_iterate(w)) { BOOST_CHECK_EQUAL(i, 198 - 2 * e); i = e++; } @@ -54,7 +54,7 @@ } e = 0; - for (const int &i : boost::adaptors::reverse(r)) { + for (const int &i : reverse_iterate(r)) { BOOST_CHECK_EQUAL(i, e++); } } diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -29,7 +29,6 @@ #include #include -#include #include #include diff --git a/src/txmempool.cpp b/src/txmempool.cpp --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -12,6 +12,7 @@ #include "consensus/validation.h" #include "policy/fees.h" #include "policy/policy.h" +#include "reverse_iterator.h" #include "streams.h" #include "timedata.h" #include "util.h" @@ -20,8 +21,6 @@ #include "validation.h" #include "version.h" -#include - CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef &_tx, const Amount _nFee, int64_t _nTime, double _entryPriority, unsigned int _entryHeight, @@ -156,7 +155,7 @@ // This maximizes the benefit of the descendant cache and guarantees that // setMemPoolChildren will be updated, an assumption made in // UpdateForDescendants. - for (const TxId &txid : boost::adaptors::reverse(txidsToUpdate)) { + for (const TxId &txid : reverse_iterate(txidsToUpdate)) { // we cache the in-mempool children to avoid duplicate updates setEntries setChildren; // calculate children from mapNextTx @@ -664,8 +663,8 @@ disconnectpool.addForBlock(vtx); std::vector entries; - for (const CTransactionRef &tx : boost::adaptors::reverse( - disconnectpool.GetQueuedTx().get())) { + for (const CTransactionRef &tx : + reverse_iterate(disconnectpool.GetQueuedTx().get())) { uint256 txid = tx->GetId(); indexed_transaction_set::iterator i = mapTx.find(txid); @@ -677,8 +676,8 @@ // Before the txs in the new block have been removed from the mempool, // update policy estimates minerPolicyEstimator->processBlock(nBlockHeight, entries); - for (const CTransactionRef &tx : boost::adaptors::reverse( - disconnectpool.GetQueuedTx().get())) { + for (const CTransactionRef &tx : + reverse_iterate(disconnectpool.GetQueuedTx().get())) { txiter it = mapTx.find(tx->GetId()); if (it != mapTx.end()) { setEntries stage; @@ -1302,7 +1301,7 @@ void DisconnectedBlockTransactions::addForBlock( const std::vector &vtx) { - for (const auto &tx : boost::adaptors::reverse(vtx)) { + for (const auto &tx : reverse_iterate(vtx)) { // If we already added it, just skip. auto it = queuedTx.find(tx->GetId()); if (it != queuedTx.end()) { @@ -1369,7 +1368,7 @@ // the mempool starting with the earliest transaction that had been // previously seen in a block. for (const CTransactionRef &tx : - boost::adaptors::reverse(queuedTx.get())) { + reverse_iterate(queuedTx.get())) { // ignore validation errors in resurrected transactions CValidationState stateDummy; if (!fAddToMempool || tx->IsCoinBase() || diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -27,6 +27,7 @@ #include "primitives/block.h" #include "primitives/transaction.h" #include "random.h" +#include "reverse_iterator.h" #include "script/script.h" #include "script/scriptcache.h" #include "script/sigcache.h" @@ -49,7 +50,6 @@ #include #include -#include #include #if defined(NDEBUG) @@ -2711,8 +2711,7 @@ nHeight = nTargetHeight; // Connect new blocks. - for (CBlockIndex *pindexConnect : - boost::adaptors::reverse(vpindexToConnect)) { + for (CBlockIndex *pindexConnect : reverse_iterate(vpindexToConnect)) { if (!ConnectTip(config, state, pindexConnect, pindexConnect == pindexMostWork ? pblock