mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 12:02:48 +01:00
partial bitcoin#16889: Add some general std::vector utility functions
This commit is contained in:
parent
f2f1843f0c
commit
46151acdb5
@ -267,6 +267,7 @@ BITCOIN_CORE_H = \
|
||||
util/string.h \
|
||||
util/time.h \
|
||||
util/threadnames.h \
|
||||
util/vector.h \
|
||||
validation.h \
|
||||
validationinterface.h \
|
||||
versionbits.h \
|
||||
|
@ -3,6 +3,7 @@
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <bech32.h>
|
||||
#include <util/vector.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -24,13 +25,6 @@ const int8_t CHARSET_REV[128] = {
|
||||
1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1
|
||||
};
|
||||
|
||||
/** Concatenate two byte arrays. */
|
||||
data Cat(data x, const data& y)
|
||||
{
|
||||
x.insert(x.end(), y.begin(), y.end());
|
||||
return x;
|
||||
}
|
||||
|
||||
/** This function will compute what 6 5-bit values to XOR into the last 6 input values, in order to
|
||||
* make the checksum 0. These 6 values are packed together in a single 30-bit integer. The higher
|
||||
* bits correspond to earlier values. */
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <util/string.h>
|
||||
#include <util/moneystr.h>
|
||||
#include <test/test_dash.h>
|
||||
#include <util/vector.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
@ -1162,4 +1163,109 @@ BOOST_AUTO_TEST_CASE(test_DirIsWritable)
|
||||
fs::remove(tmpdirname);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct Tracker
|
||||
{
|
||||
//! Points to the original object (possibly itself) we moved/copied from
|
||||
const Tracker* origin;
|
||||
//! How many copies where involved between the original object and this one (moves are not counted)
|
||||
int copies;
|
||||
|
||||
Tracker() noexcept : origin(this), copies(0) {}
|
||||
Tracker(const Tracker& t) noexcept : origin(t.origin), copies(t.copies + 1) {}
|
||||
Tracker(Tracker&& t) noexcept : origin(t.origin), copies(t.copies) {}
|
||||
Tracker& operator=(const Tracker& t) noexcept
|
||||
{
|
||||
origin = t.origin;
|
||||
copies = t.copies + 1;
|
||||
return *this;
|
||||
}
|
||||
Tracker& operator=(Tracker&& t) noexcept
|
||||
{
|
||||
origin = t.origin;
|
||||
copies = t.copies;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_tracked_vector)
|
||||
{
|
||||
Tracker t1;
|
||||
Tracker t2;
|
||||
Tracker t3;
|
||||
|
||||
BOOST_CHECK(t1.origin == &t1);
|
||||
BOOST_CHECK(t2.origin == &t2);
|
||||
BOOST_CHECK(t3.origin == &t3);
|
||||
|
||||
auto v1 = Vector(t1);
|
||||
BOOST_CHECK_EQUAL(v1.size(), 1);
|
||||
BOOST_CHECK(v1[0].origin == &t1);
|
||||
BOOST_CHECK_EQUAL(v1[0].copies, 1);
|
||||
|
||||
auto v2 = Vector(std::move(t2));
|
||||
BOOST_CHECK_EQUAL(v2.size(), 1);
|
||||
BOOST_CHECK(v2[0].origin == &t2);
|
||||
BOOST_CHECK_EQUAL(v2[0].copies, 0);
|
||||
|
||||
auto v3 = Vector(t1, std::move(t2));
|
||||
BOOST_CHECK_EQUAL(v3.size(), 2);
|
||||
BOOST_CHECK(v3[0].origin == &t1);
|
||||
BOOST_CHECK(v3[1].origin == &t2);
|
||||
BOOST_CHECK_EQUAL(v3[0].copies, 1);
|
||||
BOOST_CHECK_EQUAL(v3[1].copies, 0);
|
||||
|
||||
auto v4 = Vector(std::move(v3[0]), v3[1], std::move(t3));
|
||||
BOOST_CHECK_EQUAL(v4.size(), 3);
|
||||
BOOST_CHECK(v4[0].origin == &t1);
|
||||
BOOST_CHECK(v4[1].origin == &t2);
|
||||
BOOST_CHECK(v4[2].origin == &t3);
|
||||
BOOST_CHECK_EQUAL(v4[0].copies, 1);
|
||||
BOOST_CHECK_EQUAL(v4[1].copies, 1);
|
||||
BOOST_CHECK_EQUAL(v4[2].copies, 0);
|
||||
|
||||
auto v5 = Cat(v1, v4);
|
||||
BOOST_CHECK_EQUAL(v5.size(), 4);
|
||||
BOOST_CHECK(v5[0].origin == &t1);
|
||||
BOOST_CHECK(v5[1].origin == &t1);
|
||||
BOOST_CHECK(v5[2].origin == &t2);
|
||||
BOOST_CHECK(v5[3].origin == &t3);
|
||||
BOOST_CHECK_EQUAL(v5[0].copies, 2);
|
||||
BOOST_CHECK_EQUAL(v5[1].copies, 2);
|
||||
BOOST_CHECK_EQUAL(v5[2].copies, 2);
|
||||
BOOST_CHECK_EQUAL(v5[3].copies, 1);
|
||||
|
||||
auto v6 = Cat(std::move(v1), v3);
|
||||
BOOST_CHECK_EQUAL(v6.size(), 3);
|
||||
BOOST_CHECK(v6[0].origin == &t1);
|
||||
BOOST_CHECK(v6[1].origin == &t1);
|
||||
BOOST_CHECK(v6[2].origin == &t2);
|
||||
BOOST_CHECK_EQUAL(v6[0].copies, 1);
|
||||
BOOST_CHECK_EQUAL(v6[1].copies, 2);
|
||||
BOOST_CHECK_EQUAL(v6[2].copies, 1);
|
||||
|
||||
auto v7 = Cat(v2, std::move(v4));
|
||||
BOOST_CHECK_EQUAL(v7.size(), 4);
|
||||
BOOST_CHECK(v7[0].origin == &t2);
|
||||
BOOST_CHECK(v7[1].origin == &t1);
|
||||
BOOST_CHECK(v7[2].origin == &t2);
|
||||
BOOST_CHECK(v7[3].origin == &t3);
|
||||
BOOST_CHECK_EQUAL(v7[0].copies, 1);
|
||||
BOOST_CHECK_EQUAL(v7[1].copies, 1);
|
||||
BOOST_CHECK_EQUAL(v7[2].copies, 1);
|
||||
BOOST_CHECK_EQUAL(v7[3].copies, 0);
|
||||
|
||||
auto v8 = Cat(std::move(v2), std::move(v3));
|
||||
BOOST_CHECK_EQUAL(v8.size(), 3);
|
||||
BOOST_CHECK(v8[0].origin == &t2);
|
||||
BOOST_CHECK(v8[1].origin == &t1);
|
||||
BOOST_CHECK(v8[2].origin == &t2);
|
||||
BOOST_CHECK_EQUAL(v8[0].copies, 0);
|
||||
BOOST_CHECK_EQUAL(v8[1].copies, 1);
|
||||
BOOST_CHECK_EQUAL(v8[2].copies, 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <util/system.h>
|
||||
#include <ui_interface.h>
|
||||
#include <init.h>
|
||||
#include <util/vector.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
@ -97,7 +98,7 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) {
|
||||
// A vector is used for future extensibility, as we may want to support
|
||||
// interrupting after partial writes from multiple independent reorgs.
|
||||
batch.Erase(DB_BEST_BLOCK);
|
||||
batch.Write(DB_HEAD_BLOCKS, std::vector<uint256>{hashBlock, old_tip});
|
||||
batch.Write(DB_HEAD_BLOCKS, Vector(hashBlock, old_tip));
|
||||
|
||||
for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
|
||||
if (it->second.flags & CCoinsCacheEntry::DIRTY) {
|
||||
|
51
src/util/vector.h
Normal file
51
src/util/vector.h
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2019 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_UTIL_VECTOR_H
|
||||
#define BITCOIN_UTIL_VECTOR_H
|
||||
|
||||
#include <initializer_list>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
/** Construct a vector with the specified elements.
|
||||
*
|
||||
* This is preferable over the list initializing constructor of std::vector:
|
||||
* - It automatically infers the element type from its arguments.
|
||||
* - If any arguments are rvalue references, they will be moved into the vector
|
||||
* (list initialization always copies).
|
||||
*/
|
||||
template<typename... Args>
|
||||
inline std::vector<typename std::common_type<Args...>::type> Vector(Args&&... args)
|
||||
{
|
||||
std::vector<typename std::common_type<Args...>::type> ret;
|
||||
ret.reserve(sizeof...(args));
|
||||
// The line below uses the trick from https://www.experts-exchange.com/articles/32502/None-recursive-variadic-templates-with-std-initializer-list.html
|
||||
(void)std::initializer_list<int>{(ret.emplace_back(std::forward<Args>(args)), 0)...};
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Concatenate two vectors, moving elements. */
|
||||
template<typename V>
|
||||
inline V Cat(V v1, V&& v2)
|
||||
{
|
||||
v1.reserve(v1.size() + v2.size());
|
||||
for (auto& arg : v2) {
|
||||
v1.push_back(std::move(arg));
|
||||
}
|
||||
return v1;
|
||||
}
|
||||
|
||||
/** Concatenate two vectors. */
|
||||
template<typename V>
|
||||
inline V Cat(V v1, const V& v2)
|
||||
{
|
||||
v1.reserve(v1.size() + v2.size());
|
||||
for (const auto& arg : v2) {
|
||||
v1.push_back(arg);
|
||||
}
|
||||
return v1;
|
||||
}
|
||||
|
||||
#endif // BITCOIN_UTIL_VECTOR_H
|
Loading…
Reference in New Issue
Block a user