progminer zano miner fork https://github.com/hyle-team/progminer
This commit is contained in:
9
zano/libdevcore/CMakeLists.txt
Normal file
9
zano/libdevcore/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
file(GLOB HEADERS "*.h")
|
||||
file(GLOB SOURCES "*.cpp")
|
||||
|
||||
find_package(Threads)
|
||||
|
||||
add_library(devcore ${SOURCES} ${HEADERS})
|
||||
target_link_libraries(devcore PUBLIC Boost::boost Boost::system)
|
||||
target_link_libraries(devcore PRIVATE Threads::Threads)
|
||||
|
||||
51
zano/libdevcore/Common.h
Normal file
51
zano/libdevcore/Common.h
Normal file
@@ -0,0 +1,51 @@
|
||||
// progminer -- Ethereum miner with OpenCL, CUDA and stratum support.
|
||||
// Copyright 2018 progminer Authors.
|
||||
// Licensed under GNU General Public License, Version 3. See the LICENSE file.
|
||||
|
||||
/// @file
|
||||
/// Very common stuff (i.e. that every other header needs except vector_ref.h).
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "vector_ref.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/multiprecision/cpp_int.hpp>
|
||||
|
||||
using byte = uint8_t;
|
||||
|
||||
namespace dev
|
||||
{
|
||||
// Binary data types.
|
||||
using bytes = std::vector<byte>;
|
||||
using bytesRef = vector_ref<byte>;
|
||||
using bytesConstRef = vector_ref<byte const>;
|
||||
|
||||
// Numeric types.
|
||||
using bigint = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<>>;
|
||||
using u64 = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<64, 64,
|
||||
boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
|
||||
using u128 = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<128, 128,
|
||||
boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
|
||||
using u256 = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<256, 256,
|
||||
boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
|
||||
using u160 = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<160, 160,
|
||||
boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
|
||||
using u512 = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<512, 512,
|
||||
boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
|
||||
|
||||
// Null/Invalid values for convenience.
|
||||
static const u256 Invalid256 = ~(u256)0;
|
||||
|
||||
/// Converts arbitrary value to string representation using std::stringstream.
|
||||
template <class _T>
|
||||
std::string toString(_T const& _t)
|
||||
{
|
||||
std::ostringstream o;
|
||||
o << _t;
|
||||
return o.str();
|
||||
}
|
||||
|
||||
} // namespace dev
|
||||
201
zano/libdevcore/CommonData.cpp
Normal file
201
zano/libdevcore/CommonData.cpp
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
This file is part of progminer.
|
||||
|
||||
progminer is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
progminer is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with progminer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "CommonData.h"
|
||||
#include "Exceptions.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace dev;
|
||||
|
||||
int dev::fromHex(char _i, WhenError _throw)
|
||||
{
|
||||
if (_i >= '0' && _i <= '9')
|
||||
return _i - '0';
|
||||
if (_i >= 'a' && _i <= 'f')
|
||||
return _i - 'a' + 10;
|
||||
if (_i >= 'A' && _i <= 'F')
|
||||
return _i - 'A' + 10;
|
||||
if (_throw == WhenError::Throw)
|
||||
BOOST_THROW_EXCEPTION(BadHexCharacter() << errinfo_invalidSymbol(_i));
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
bytes dev::fromHex(std::string const& _s, WhenError _throw)
|
||||
{
|
||||
unsigned s = (_s[0] == '0' && _s[1] == 'x') ? 2 : 0;
|
||||
std::vector<uint8_t> ret;
|
||||
ret.reserve((_s.size() - s + 1) / 2);
|
||||
|
||||
if (_s.size() % 2)
|
||||
{
|
||||
int h = fromHex(_s[s++], WhenError::DontThrow);
|
||||
if (h != -1)
|
||||
ret.push_back(h);
|
||||
else if (_throw == WhenError::Throw)
|
||||
BOOST_THROW_EXCEPTION(BadHexCharacter());
|
||||
else
|
||||
return bytes();
|
||||
}
|
||||
for (unsigned i = s; i < _s.size(); i += 2)
|
||||
{
|
||||
int h = fromHex(_s[i], WhenError::DontThrow);
|
||||
int l = fromHex(_s[i + 1], WhenError::DontThrow);
|
||||
if (h != -1 && l != -1)
|
||||
ret.push_back((byte)(h * 16 + l));
|
||||
else if (_throw == WhenError::Throw)
|
||||
BOOST_THROW_EXCEPTION(BadHexCharacter());
|
||||
else
|
||||
return bytes();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool dev::setenv(const char name[], const char value[], bool override)
|
||||
{
|
||||
#if _WIN32
|
||||
if (!override && std::getenv(name) != nullptr)
|
||||
return true;
|
||||
|
||||
return ::_putenv_s(name, value) == 0;
|
||||
#else
|
||||
return ::setenv(name, value, override ? 1 : 0) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string dev::getTargetFromDiff(double diff, HexPrefix _prefix)
|
||||
{
|
||||
using namespace boost::multiprecision;
|
||||
using BigInteger = boost::multiprecision::cpp_int;
|
||||
|
||||
static BigInteger base("0x00000000ffff0000000000000000000000000000000000000000000000000000");
|
||||
BigInteger product;
|
||||
|
||||
if (diff == 0)
|
||||
{
|
||||
product = BigInteger("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
||||
}
|
||||
else
|
||||
{
|
||||
diff = 1 / diff;
|
||||
|
||||
BigInteger idiff(diff);
|
||||
product = base * idiff;
|
||||
|
||||
std::string sdiff = boost::lexical_cast<std::string>(diff);
|
||||
size_t ldiff = sdiff.length();
|
||||
size_t offset = sdiff.find(".");
|
||||
|
||||
if (offset != std::string::npos)
|
||||
{
|
||||
// Number of decimal places
|
||||
size_t precision = (ldiff - 1) - offset;
|
||||
|
||||
// Effective sequence of decimal places
|
||||
string decimals = sdiff.substr(offset + 1);
|
||||
|
||||
// Strip leading zeroes. If a string begins with
|
||||
// 0 or 0x boost parser considers it hex
|
||||
decimals = decimals.erase(0, decimals.find_first_not_of('0'));
|
||||
|
||||
// Build up the divisor as string - just in case
|
||||
// parser does some implicit conversion with 10^precision
|
||||
string decimalDivisor = "1";
|
||||
decimalDivisor.resize(precision + 1, '0');
|
||||
|
||||
// This is the multiplier for the decimal part
|
||||
BigInteger multiplier(decimals);
|
||||
|
||||
// This is the divisor for the decimal part
|
||||
BigInteger divisor(decimalDivisor);
|
||||
|
||||
BigInteger decimalproduct;
|
||||
decimalproduct = base * multiplier;
|
||||
decimalproduct /= divisor;
|
||||
|
||||
// Add the computed decimal part
|
||||
// to product
|
||||
product += decimalproduct;
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize to 64 chars hex with "0x" prefix
|
||||
stringstream ss;
|
||||
ss << (_prefix == HexPrefix::Add ? "0x" : "") << setw(64) << setfill('0') << std::hex
|
||||
<< product;
|
||||
|
||||
string target = ss.str();
|
||||
boost::algorithm::to_lower(target);
|
||||
return target;
|
||||
}
|
||||
|
||||
double dev::getHashesToTarget(string _target)
|
||||
{
|
||||
using namespace boost::multiprecision;
|
||||
using BigInteger = boost::multiprecision::cpp_int;
|
||||
|
||||
static BigInteger dividend(
|
||||
"0xffff000000000000000000000000000000000000000000000000000000000000");
|
||||
BigInteger divisor(_target);
|
||||
return double(dividend / divisor);
|
||||
}
|
||||
|
||||
std::string dev::getScaledSize(double _value, double _divisor, int _precision, string _sizes[],
|
||||
size_t _numsizes, ScaleSuffix _suffix)
|
||||
{
|
||||
double _newvalue = _value;
|
||||
size_t i = 0;
|
||||
while (_newvalue > _divisor && i <= (_numsizes - 1))
|
||||
{
|
||||
_newvalue /= _divisor;
|
||||
i++;
|
||||
}
|
||||
|
||||
std::stringstream _ret;
|
||||
_ret << fixed << setprecision(_precision) << _newvalue;
|
||||
if (_suffix == ScaleSuffix::Add)
|
||||
_ret << " " << _sizes[i];
|
||||
return _ret.str();
|
||||
}
|
||||
|
||||
std::string dev::getFormattedHashes(double _hr, ScaleSuffix _suffix, int _precision)
|
||||
{
|
||||
static string suffixes[] = {"h", "Kh", "Mh", "Gh"};
|
||||
return dev::getScaledSize(_hr, 1000.0, _precision, suffixes, 4, _suffix);
|
||||
}
|
||||
|
||||
std::string dev::getFormattedMemory(double _mem, ScaleSuffix _suffix, int _precision)
|
||||
{
|
||||
static string suffixes[] = {"B", "KB", "MB", "GB"};
|
||||
return dev::getScaledSize(_mem, 1024.0, _precision, suffixes, 4, _suffix);
|
||||
}
|
||||
|
||||
std::string dev::padLeft(std::string _value, size_t _length, char _fillChar)
|
||||
{
|
||||
if (_length > _value.size())
|
||||
_value.insert(0, (_length - _value.size()), _fillChar);
|
||||
return _value;
|
||||
}
|
||||
|
||||
std::string dev::padRight(std::string _value, size_t _length, char _fillChar)
|
||||
{
|
||||
if (_length > _value.size())
|
||||
_value.resize(_length, _fillChar);
|
||||
return _value;
|
||||
}
|
||||
253
zano/libdevcore/CommonData.h
Normal file
253
zano/libdevcore/CommonData.h
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
This file is part of progminer.
|
||||
|
||||
progminer is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
progminer is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with progminer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** @file CommonData.h
|
||||
* @author Gav Wood <i@gavwood.com>
|
||||
* @date 2014
|
||||
*
|
||||
* Shared algorithms and data types.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
namespace dev
|
||||
{
|
||||
// String conversion functions, mainly to/from hex/nibble/byte representations.
|
||||
|
||||
enum class WhenError
|
||||
{
|
||||
DontThrow = 0,
|
||||
Throw = 1,
|
||||
};
|
||||
|
||||
enum class HexPrefix
|
||||
{
|
||||
DontAdd = 0,
|
||||
Add = 1,
|
||||
};
|
||||
|
||||
enum class ScaleSuffix
|
||||
{
|
||||
DontAdd = 0,
|
||||
Add = 1
|
||||
};
|
||||
|
||||
/// Convert a series of bytes to the corresponding string of hex duplets.
|
||||
/// @param _w specifies the width of the first of the elements. Defaults to two - enough to
|
||||
/// represent a byte.
|
||||
/// @example toHex("A\x69") == "4169"
|
||||
template <class T>
|
||||
std::string toHex(T const& _data, int _w = 2, HexPrefix _prefix = HexPrefix::DontAdd)
|
||||
{
|
||||
std::ostringstream ret;
|
||||
unsigned ii = 0;
|
||||
for (auto i : _data)
|
||||
ret << std::hex << std::setfill('0') << std::setw(ii++ ? 2 : _w)
|
||||
<< (int)(typename std::make_unsigned<decltype(i)>::type)i;
|
||||
return (_prefix == HexPrefix::Add) ? "0x" + ret.str() : ret.str();
|
||||
}
|
||||
|
||||
/// Converts a (printable) ASCII hex character into the correspnding integer value.
|
||||
/// @example fromHex('A') == 10 && fromHex('f') == 15 && fromHex('5') == 5
|
||||
int fromHex(char _i, WhenError _throw);
|
||||
|
||||
/// Converts a (printable) ASCII hex string into the corresponding byte stream.
|
||||
/// @example fromHex("41626261") == asBytes("Abba")
|
||||
/// If _throw = ThrowType::DontThrow, it replaces bad hex characters with 0's, otherwise it will
|
||||
/// throw an exception.
|
||||
bytes fromHex(std::string const& _s, WhenError _throw = WhenError::DontThrow);
|
||||
|
||||
/// Converts byte array to a string containing the same (binary) data. Unless
|
||||
/// the byte array happens to contain ASCII data, this won't be printable.
|
||||
inline std::string asString(bytes const& _b)
|
||||
{
|
||||
return std::string((char const*)_b.data(), (char const*)(_b.data() + _b.size()));
|
||||
}
|
||||
|
||||
/// Converts a string to a byte array containing the string's (byte) data.
|
||||
inline bytes asBytes(std::string const& _b)
|
||||
{
|
||||
return bytes((byte const*)_b.data(), (byte const*)(_b.data() + _b.size()));
|
||||
}
|
||||
|
||||
|
||||
// Big-endian to/from host endian conversion functions.
|
||||
|
||||
/// Converts a templated integer value to the big-endian byte-stream represented on a templated
|
||||
/// collection. The size of the collection object will be unchanged. If it is too small, it will not
|
||||
/// represent the value properly, if too big then the additional elements will be zeroed out.
|
||||
/// @a Out will typically be either std::string or bytes.
|
||||
/// @a T will typically by unsigned, u160, u256 or bigint.
|
||||
template <class T, class Out>
|
||||
inline void toBigEndian(T _val, Out& o_out)
|
||||
{
|
||||
static_assert(std::is_same<bigint, T>::value || !std::numeric_limits<T>::is_signed,
|
||||
"only unsigned types or bigint supported"); // bigint does not carry sign bit on shift
|
||||
for (auto i = o_out.size(); i != 0; _val >>= 8, i--)
|
||||
{
|
||||
T v = _val & (T)0xff;
|
||||
o_out[i - 1] = (typename Out::value_type)(uint8_t)v;
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a big-endian byte-stream represented on a templated collection to a templated integer
|
||||
/// value.
|
||||
/// @a _In will typically be either std::string or bytes.
|
||||
/// @a T will typically by unsigned, u160, u256 or bigint.
|
||||
template <class T, class _In>
|
||||
inline T fromBigEndian(_In const& _bytes)
|
||||
{
|
||||
T ret = (T)0;
|
||||
for (auto i : _bytes)
|
||||
ret =
|
||||
(T)((ret << 8) | (byte)(typename std::make_unsigned<typename _In::value_type>::type)i);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Convenience functions for toBigEndian
|
||||
inline bytes toBigEndian(u256 _val)
|
||||
{
|
||||
bytes ret(32);
|
||||
toBigEndian(std::move(_val), ret);
|
||||
return ret;
|
||||
}
|
||||
inline bytes toBigEndian(u160 _val)
|
||||
{
|
||||
bytes ret(20);
|
||||
toBigEndian(_val, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Convenience function for toBigEndian.
|
||||
/// @returns a byte array just big enough to represent @a _val.
|
||||
template <class T>
|
||||
inline bytes toCompactBigEndian(T _val, unsigned _min = 0)
|
||||
{
|
||||
static_assert(std::is_same<bigint, T>::value || !std::numeric_limits<T>::is_signed,
|
||||
"only unsigned types or bigint supported"); // bigint does not carry sign bit on shift
|
||||
int i = 0;
|
||||
for (T v = _val; v; ++i, v >>= 8)
|
||||
{
|
||||
}
|
||||
bytes ret(std::max<unsigned>(_min, i), 0);
|
||||
toBigEndian(_val, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Convenience function for conversion of a u256 to hex
|
||||
inline std::string toHex(u256 val, HexPrefix prefix = HexPrefix::DontAdd)
|
||||
{
|
||||
std::string str = toHex(toBigEndian(val));
|
||||
return (prefix == HexPrefix::Add) ? "0x" + str : str;
|
||||
}
|
||||
|
||||
inline std::string toHex(uint64_t _n, HexPrefix _prefix = HexPrefix::DontAdd, int _bytes = 16)
|
||||
{
|
||||
// sizeof returns the number of bytes (not the number of bits)
|
||||
// thus if CHAR_BIT != 8 sizeof(uint64_t) will return != 8
|
||||
// Use fixed constant multiplier of 16
|
||||
std::ostringstream ret;
|
||||
ret << std::hex << std::setfill('0') << std::setw(_bytes) << _n;
|
||||
return (_prefix == HexPrefix::Add) ? "0x" + ret.str() : ret.str();
|
||||
}
|
||||
|
||||
inline std::string toHex(uint32_t _n, HexPrefix _prefix = HexPrefix::DontAdd, int _bytes = 8)
|
||||
{
|
||||
// sizeof returns the number of bytes (not the number of bits)
|
||||
// thus if CHAR_BIT != 8 sizeof(uint64_t) will return != 4
|
||||
// Use fixed constant multiplier of 8
|
||||
std::ostringstream ret;
|
||||
ret << std::hex << std::setfill('0') << std::setw(_bytes) << _n;
|
||||
return (_prefix == HexPrefix::Add) ? "0x" + ret.str() : ret.str();
|
||||
}
|
||||
|
||||
inline std::string toCompactHex(uint64_t _n, HexPrefix _prefix = HexPrefix::DontAdd)
|
||||
{
|
||||
std::ostringstream ret;
|
||||
ret << std::hex << _n;
|
||||
return (_prefix == HexPrefix::Add) ? "0x" + ret.str() : ret.str();
|
||||
}
|
||||
|
||||
inline std::string toCompactHex(uint32_t _n, HexPrefix _prefix = HexPrefix::DontAdd)
|
||||
{
|
||||
std::ostringstream ret;
|
||||
ret << std::hex << _n;
|
||||
return (_prefix == HexPrefix::Add) ? "0x" + ret.str() : ret.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Algorithms for string and string-like collections.
|
||||
|
||||
/// Escapes a string into the C-string representation.
|
||||
/// @p _all if true will escape all characters, not just the unprintable ones.
|
||||
std::string escaped(std::string const& _s, bool _all = true);
|
||||
|
||||
// General datatype convenience functions.
|
||||
|
||||
/// Determine bytes required to encode the given integer value. @returns 0 if @a _i is zero.
|
||||
template <class T>
|
||||
inline unsigned bytesRequired(T _i)
|
||||
{
|
||||
static_assert(std::is_same<bigint, T>::value || !std::numeric_limits<T>::is_signed,
|
||||
"only unsigned types or bigint supported"); // bigint does not carry sign bit on shift
|
||||
unsigned i = 0;
|
||||
for (; _i != 0; ++i, _i >>= 8)
|
||||
{
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/// Sets environment variable.
|
||||
///
|
||||
/// Portable wrapper for setenv / _putenv C library functions.
|
||||
bool setenv(const char name[], const char value[], bool override = false);
|
||||
|
||||
/// Gets a target hash from given difficulty
|
||||
std::string getTargetFromDiff(double diff, HexPrefix _prefix = HexPrefix::Add);
|
||||
|
||||
/// Gets the difficulty expressed in hashes to target
|
||||
double getHashesToTarget(std::string _target);
|
||||
|
||||
/// Generic function to scale a value
|
||||
std::string getScaledSize(double _value, double _divisor, int _precision, std::string _sizes[],
|
||||
size_t _numsizes, ScaleSuffix _suffix = ScaleSuffix::Add);
|
||||
|
||||
/// Formats hashrate
|
||||
std::string getFormattedHashes(double _hr, ScaleSuffix _suffix = ScaleSuffix::Add, int _precision = 2);
|
||||
|
||||
/// Formats hashrate
|
||||
std::string getFormattedMemory(
|
||||
double _mem, ScaleSuffix _suffix = ScaleSuffix::Add, int _precision = 2);
|
||||
|
||||
/// Adjust string to a fixed length filling chars to the Left
|
||||
std::string padLeft(std::string _value, size_t _length, char _fillChar);
|
||||
|
||||
/// Adjust string to a fixed length filling chars to the Right
|
||||
std::string padRight(std::string _value, size_t _length, char _fillChar);
|
||||
|
||||
} // namespace dev
|
||||
70
zano/libdevcore/Exceptions.h
Normal file
70
zano/libdevcore/Exceptions.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
This file is part of progminer.
|
||||
|
||||
progminer is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
progminer is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with progminer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** @file Exceptions.h
|
||||
* @author Gav Wood <i@gavwood.com>
|
||||
* @date 2014
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
#include <boost/exception/all.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include "CommonData.h"
|
||||
#include "FixedHash.h"
|
||||
|
||||
namespace dev
|
||||
{
|
||||
/// Base class for all exceptions.
|
||||
struct Exception : virtual std::exception, virtual boost::exception
|
||||
{
|
||||
Exception(const std::string& _message = std::string()) : m_message(std::move(_message)) {}
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
return m_message.empty() ? std::exception::what() : m_message.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_message;
|
||||
};
|
||||
|
||||
#define DEV_SIMPLE_EXCEPTION(X) \
|
||||
struct X : virtual Exception \
|
||||
{ \
|
||||
const char* what() const noexcept override { return #X; } \
|
||||
}
|
||||
|
||||
|
||||
DEV_SIMPLE_EXCEPTION(BadHexCharacter);
|
||||
|
||||
struct ExternalFunctionFailure : virtual Exception
|
||||
{
|
||||
public:
|
||||
ExternalFunctionFailure(const std::string& _f) : Exception("Function " + _f + "() failed.") {}
|
||||
};
|
||||
|
||||
// error information to be added to exceptions
|
||||
using errinfo_invalidSymbol = boost::error_info<struct tag_invalidSymbol, char>;
|
||||
using errinfo_comment = boost::error_info<struct tag_comment, std::string>;
|
||||
using errinfo_required = boost::error_info<struct tag_required, bigint>;
|
||||
using errinfo_got = boost::error_info<struct tag_got, bigint>;
|
||||
using RequirementError = boost::tuple<errinfo_required, errinfo_got>;
|
||||
|
||||
} // namespace dev
|
||||
29
zano/libdevcore/FixedHash.cpp
Normal file
29
zano/libdevcore/FixedHash.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
This file is part of progminer.
|
||||
|
||||
progminer is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
progminer is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with progminer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** @file FixedHash.cpp
|
||||
* @author Gav Wood <i@gavwood.com>
|
||||
* @date 2014
|
||||
*/
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "FixedHash.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace dev;
|
||||
|
||||
std::random_device dev::s_fixedHashEngine;
|
||||
338
zano/libdevcore/FixedHash.h
Normal file
338
zano/libdevcore/FixedHash.h
Normal file
@@ -0,0 +1,338 @@
|
||||
/*
|
||||
This file is part of progminer.
|
||||
|
||||
progminer is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
progminer is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with progminer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** @file FixedHash.h
|
||||
* @author Gav Wood <i@gavwood.com>
|
||||
* @date 2014
|
||||
*
|
||||
* The FixedHash fixed-size "hash" container type.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <random>
|
||||
|
||||
#include "CommonData.h"
|
||||
|
||||
namespace dev
|
||||
{
|
||||
extern std::random_device s_fixedHashEngine;
|
||||
|
||||
/// Fixed-size raw-byte array container type, with an API optimised for storing hashes.
|
||||
/// Transparently converts to/from the corresponding arithmetic type; this will
|
||||
/// assume the data contained in the hash is big-endian.
|
||||
template <unsigned N>
|
||||
class FixedHash
|
||||
{
|
||||
public:
|
||||
#if defined(_WIN32)
|
||||
const char* k_ellipsis = "...";
|
||||
#else
|
||||
const char* k_ellipsis = "\342\200\246";
|
||||
#endif
|
||||
|
||||
/// The corresponding arithmetic type.
|
||||
using Arith = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<N * 8, N * 8,
|
||||
boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
|
||||
|
||||
/// The size of the container.
|
||||
enum
|
||||
{
|
||||
size = N
|
||||
};
|
||||
|
||||
/// A dummy flag to avoid accidental construction from pointer.
|
||||
enum ConstructFromPointerType
|
||||
{
|
||||
ConstructFromPointer
|
||||
};
|
||||
|
||||
/// Method to convert from a string.
|
||||
enum ConstructFromHashType
|
||||
{
|
||||
AlignLeft,
|
||||
AlignRight,
|
||||
FailIfDifferent
|
||||
};
|
||||
|
||||
/// Construct an empty hash.
|
||||
FixedHash() { m_data.fill(0); }
|
||||
|
||||
/// Construct from another hash, filling with zeroes or cropping as necessary.
|
||||
template <unsigned M>
|
||||
explicit FixedHash(FixedHash<M> const& _h, ConstructFromHashType _t = AlignLeft)
|
||||
{
|
||||
m_data.fill(0);
|
||||
unsigned c = std::min(M, N);
|
||||
for (unsigned i = 0; i < c; ++i)
|
||||
m_data[_t == AlignRight ? N - 1 - i : i] = _h[_t == AlignRight ? M - 1 - i : i];
|
||||
}
|
||||
|
||||
/// Convert from the corresponding arithmetic type.
|
||||
FixedHash(Arith const& _arith) { toBigEndian(_arith, m_data); }
|
||||
|
||||
/// Convert from unsigned
|
||||
explicit FixedHash(unsigned _u) { toBigEndian(_u, m_data); }
|
||||
|
||||
/// Explicitly construct, copying from a byte array.
|
||||
explicit FixedHash(bytes const& _b, ConstructFromHashType _t = FailIfDifferent)
|
||||
{
|
||||
if (_b.size() == N)
|
||||
memcpy(m_data.data(), _b.data(), std::min<unsigned>(_b.size(), N));
|
||||
else
|
||||
{
|
||||
m_data.fill(0);
|
||||
if (_t != FailIfDifferent)
|
||||
{
|
||||
auto c = std::min<unsigned>(_b.size(), N);
|
||||
for (unsigned i = 0; i < c; ++i)
|
||||
m_data[_t == AlignRight ? N - 1 - i : i] =
|
||||
_b[_t == AlignRight ? _b.size() - 1 - i : i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Explicitly construct, copying from a byte array.
|
||||
explicit FixedHash(bytesConstRef _b, ConstructFromHashType _t = FailIfDifferent)
|
||||
{
|
||||
if (_b.size() == N)
|
||||
memcpy(m_data.data(), _b.data(), std::min<unsigned>(_b.size(), N));
|
||||
else
|
||||
{
|
||||
m_data.fill(0);
|
||||
if (_t != FailIfDifferent)
|
||||
{
|
||||
auto c = std::min<unsigned>(_b.size(), N);
|
||||
for (unsigned i = 0; i < c; ++i)
|
||||
m_data[_t == AlignRight ? N - 1 - i : i] =
|
||||
_b[_t == AlignRight ? _b.size() - 1 - i : i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Explicitly construct, copying from a bytes in memory with given pointer.
|
||||
explicit FixedHash(byte const* _bs, ConstructFromPointerType /*unused*/)
|
||||
{
|
||||
memcpy(m_data.data(), _bs, N);
|
||||
}
|
||||
|
||||
/// Explicitly construct, copying from a string.
|
||||
explicit FixedHash(std::string const& _s)
|
||||
: FixedHash(fromHex(_s, WhenError::Throw), FailIfDifferent)
|
||||
{}
|
||||
|
||||
/// Convert to arithmetic type.
|
||||
operator Arith() const { return fromBigEndian<Arith>(m_data); }
|
||||
|
||||
/// @returns true iff this is the empty hash.
|
||||
explicit operator bool() const
|
||||
{
|
||||
return std::any_of(m_data.begin(), m_data.end(), [](byte _b) { return _b != 0; });
|
||||
}
|
||||
|
||||
// The obvious comparison operators.
|
||||
bool operator==(FixedHash const& _c) const { return m_data == _c.m_data; }
|
||||
bool operator!=(FixedHash const& _c) const { return m_data != _c.m_data; }
|
||||
bool operator<(FixedHash const& _c) const
|
||||
{
|
||||
for (unsigned i = 0; i < N; ++i)
|
||||
{
|
||||
if (m_data[i] < _c.m_data[i])
|
||||
return true;
|
||||
if (m_data[i] > _c.m_data[i])
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool operator>=(FixedHash const& _c) const { return !operator<(_c); }
|
||||
bool operator<=(FixedHash const& _c) const { return operator==(_c) || operator<(_c); }
|
||||
bool operator>(FixedHash const& _c) const { return !operator<=(_c); }
|
||||
|
||||
// The obvious binary operators.
|
||||
FixedHash& operator^=(FixedHash const& _c)
|
||||
{
|
||||
for (unsigned i = 0; i < N; ++i)
|
||||
m_data[i] ^= _c.m_data[i];
|
||||
return *this;
|
||||
}
|
||||
FixedHash operator^(FixedHash const& _c) const { return FixedHash(*this) ^= _c; }
|
||||
FixedHash& operator|=(FixedHash const& _c)
|
||||
{
|
||||
for (unsigned i = 0; i < N; ++i)
|
||||
m_data[i] |= _c.m_data[i];
|
||||
return *this;
|
||||
}
|
||||
FixedHash operator|(FixedHash const& _c) const { return FixedHash(*this) |= _c; }
|
||||
FixedHash& operator&=(FixedHash const& _c)
|
||||
{
|
||||
for (unsigned i = 0; i < N; ++i)
|
||||
m_data[i] &= _c.m_data[i];
|
||||
return *this;
|
||||
}
|
||||
FixedHash operator&(FixedHash const& _c) const { return FixedHash(*this) &= _c; }
|
||||
FixedHash operator~() const
|
||||
{
|
||||
FixedHash ret;
|
||||
for (unsigned i = 0; i < N; ++i)
|
||||
ret[i] = ~m_data[i];
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Big-endian increment.
|
||||
FixedHash& operator++()
|
||||
{
|
||||
for (unsigned i = size; i > 0 && !++m_data[--i];)
|
||||
{
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// @returns a particular byte from the hash.
|
||||
byte& operator[](unsigned _i) { return m_data[_i]; }
|
||||
/// @returns a particular byte from the hash.
|
||||
byte operator[](unsigned _i) const { return m_data[_i]; }
|
||||
|
||||
/// @returns an abridged version of the hash as a user-readable hex string.
|
||||
|
||||
std::string abridged() const { return toHex(ref().cropped(0, 4)) + k_ellipsis; }
|
||||
|
||||
/// @returns the hash as a user-readable hex string.
|
||||
std::string hex(HexPrefix _prefix = HexPrefix::DontAdd) const { return toHex(ref(), 2, _prefix); }
|
||||
|
||||
/// @returns a mutable byte vector_ref to the object's data.
|
||||
bytesRef ref() { return bytesRef(m_data.data(), N); }
|
||||
|
||||
/// @returns a constant byte vector_ref to the object's data.
|
||||
bytesConstRef ref() const { return bytesConstRef(m_data.data(), N); }
|
||||
|
||||
/// @returns a mutable byte pointer to the object's data.
|
||||
byte* data() { return m_data.data(); }
|
||||
|
||||
/// @returns a constant byte pointer to the object's data.
|
||||
byte const* data() const { return m_data.data(); }
|
||||
|
||||
/// Populate with random data.
|
||||
template <class Engine>
|
||||
void randomize(Engine& _eng)
|
||||
{
|
||||
for (auto& i : m_data)
|
||||
i = (uint8_t)std::uniform_int_distribution<uint16_t>(0, 255)(_eng);
|
||||
}
|
||||
|
||||
/// @returns a random valued object.
|
||||
static FixedHash random()
|
||||
{
|
||||
FixedHash ret;
|
||||
ret.randomize(s_fixedHashEngine);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct hash
|
||||
{
|
||||
/// Make a hash of the object's data.
|
||||
size_t operator()(FixedHash const& _value) const
|
||||
{
|
||||
return boost::hash_range(_value.m_data.cbegin(), _value.m_data.cend());
|
||||
}
|
||||
};
|
||||
|
||||
void clear() { m_data.fill(0); }
|
||||
|
||||
private:
|
||||
std::array<byte, N> m_data; ///< The binary data.
|
||||
};
|
||||
|
||||
/// Fast equality operator for h256.
|
||||
template <>
|
||||
inline bool FixedHash<32>::operator==(FixedHash<32> const& _other) const
|
||||
{
|
||||
const uint64_t* hash1 = (const uint64_t*)data();
|
||||
const uint64_t* hash2 = (const uint64_t*)_other.data();
|
||||
return (hash1[0] == hash2[0]) && (hash1[1] == hash2[1]) && (hash1[2] == hash2[2]) &&
|
||||
(hash1[3] == hash2[3]);
|
||||
}
|
||||
|
||||
/// Fast std::hash compatible hash function object for h256.
|
||||
template <>
|
||||
inline size_t FixedHash<32>::hash::operator()(FixedHash<32> const& value) const
|
||||
{
|
||||
uint64_t const* data = reinterpret_cast<uint64_t const*>(value.data());
|
||||
return boost::hash_range(data, data + 4);
|
||||
}
|
||||
|
||||
/// Stream I/O for the FixedHash class.
|
||||
template <unsigned N>
|
||||
inline std::ostream& operator<<(std::ostream& _out, FixedHash<N> const& _h)
|
||||
{
|
||||
_out << std::noshowbase << std::hex << std::setfill('0');
|
||||
for (unsigned i = 0; i < N; ++i)
|
||||
_out << std::setw(2) << (int)_h[i];
|
||||
_out << std::dec;
|
||||
return _out;
|
||||
}
|
||||
|
||||
// Common types of FixedHash.
|
||||
using h2048 = FixedHash<256>;
|
||||
using h1024 = FixedHash<128>;
|
||||
using h520 = FixedHash<65>;
|
||||
using h512 = FixedHash<64>;
|
||||
using h256 = FixedHash<32>;
|
||||
using h160 = FixedHash<20>;
|
||||
using h128 = FixedHash<16>;
|
||||
using h64 = FixedHash<8>;
|
||||
using h512s = std::vector<h512>;
|
||||
using h256s = std::vector<h256>;
|
||||
using h160s = std::vector<h160>;
|
||||
|
||||
inline std::string toString(h256s const& _bs)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "[ ";
|
||||
for (auto i : _bs)
|
||||
out << i.abridged() << ", ";
|
||||
out << "]";
|
||||
return out.str();
|
||||
}
|
||||
|
||||
} // namespace dev
|
||||
|
||||
namespace std
|
||||
{
|
||||
/// Forward std::hash<dev::FixedHash> to dev::FixedHash::hash.
|
||||
template <>
|
||||
struct hash<dev::h64> : dev::h64::hash
|
||||
{
|
||||
};
|
||||
template <>
|
||||
struct hash<dev::h128> : dev::h128::hash
|
||||
{
|
||||
};
|
||||
template <>
|
||||
struct hash<dev::h160> : dev::h160::hash
|
||||
{
|
||||
};
|
||||
template <>
|
||||
struct hash<dev::h256> : dev::h256::hash
|
||||
{
|
||||
};
|
||||
template <>
|
||||
struct hash<dev::h512> : dev::h512::hash
|
||||
{
|
||||
};
|
||||
} // namespace std
|
||||
76
zano/libdevcore/Guards.h
Normal file
76
zano/libdevcore/Guards.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
This file is part of progminer.
|
||||
|
||||
progminer is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
progminer is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with progminer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** @file Guards.h
|
||||
* @author Gav Wood <i@gavwood.com>
|
||||
* @date 2014
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
|
||||
namespace dev
|
||||
{
|
||||
using Mutex = std::mutex;
|
||||
using Guard = std::lock_guard<std::mutex>;
|
||||
using UniqueGuard = std::unique_lock<std::mutex>;
|
||||
|
||||
template <class GuardType, class MutexType>
|
||||
struct GenericGuardBool : GuardType
|
||||
{
|
||||
GenericGuardBool(MutexType& _m) : GuardType(_m) {}
|
||||
bool b = true;
|
||||
};
|
||||
|
||||
/** @brief Simple block guard.
|
||||
* The expression/block following is guarded though the given mutex.
|
||||
* Usage:
|
||||
* @code
|
||||
* Mutex m;
|
||||
* unsigned d;
|
||||
* ...
|
||||
* ETH_(m) d = 1;
|
||||
* ...
|
||||
* ETH_(m) { for (auto d = 10; d > 0; --d) foo(d); d = 0; }
|
||||
* @endcode
|
||||
*
|
||||
* There are several variants of this basic mechanism for different Mutex types and Guards.
|
||||
*
|
||||
* There is also the UNGUARD variant which allows an unguarded expression/block to exist within a
|
||||
* guarded expression. eg:
|
||||
*
|
||||
* @code
|
||||
* Mutex m;
|
||||
* int d;
|
||||
* ...
|
||||
* ETH_GUARDED(m)
|
||||
* {
|
||||
* for (auto d = 50; d > 25; --d)
|
||||
* foo(d);
|
||||
* ETH_UNGUARDED(m)
|
||||
* bar();
|
||||
* for (; d > 0; --d)
|
||||
* foo(d);
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
#define DEV_GUARDED(MUTEX) \
|
||||
for (GenericGuardBool<Guard, Mutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
|
||||
|
||||
} // namespace dev
|
||||
134
zano/libdevcore/Log.cpp
Normal file
134
zano/libdevcore/Log.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
This file is part of progminer.
|
||||
|
||||
progminer is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
progminer is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with progminer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
#include <map>
|
||||
#include <thread>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include "Guards.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace dev;
|
||||
|
||||
//⊳⊲◀▶■▣▢□▷◁▧▨▩▲◆◉◈◇◎●◍◌○◼☑☒☎☢☣☰☀♽♥♠✩✭❓✔✓✖✕✘✓✔✅⚒⚡⦸⬌∅⁕«««»»»⚙
|
||||
|
||||
// Logging
|
||||
unsigned g_logOptions = 0;
|
||||
bool g_logNoColor = false;
|
||||
bool g_logSyslog = false;
|
||||
bool g_logStdout = false;
|
||||
|
||||
const char* LogChannel::name()
|
||||
{
|
||||
return EthGray "..";
|
||||
}
|
||||
const char* WarnChannel::name()
|
||||
{
|
||||
return EthRed " X";
|
||||
}
|
||||
const char* NoteChannel::name()
|
||||
{
|
||||
return EthBlue " i";
|
||||
}
|
||||
|
||||
LogOutputStreamBase::LogOutputStreamBase(char const* _id)
|
||||
{
|
||||
static std::locale logLocl = std::locale("");
|
||||
m_sstr.imbue(logLocl);
|
||||
if (g_logSyslog)
|
||||
m_sstr << std::left << std::setw(8) << getThreadName() << " " EthReset;
|
||||
else
|
||||
{
|
||||
time_t rawTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
||||
char buf[24];
|
||||
if (strftime(buf, 24, "%X", localtime(&rawTime)) == 0)
|
||||
buf[0] = '\0'; // empty if case strftime fails
|
||||
m_sstr << _id << " " EthViolet << buf << " " EthBlue << std::left << std::setw(9)
|
||||
<< getThreadName() << " " EthReset;
|
||||
}
|
||||
}
|
||||
|
||||
/// Associate a name with each thread for nice logging.
|
||||
struct ThreadLocalLogName
|
||||
{
|
||||
ThreadLocalLogName(char const* _name) { name = _name; }
|
||||
thread_local static char const* name;
|
||||
};
|
||||
|
||||
thread_local char const* ThreadLocalLogName::name;
|
||||
|
||||
ThreadLocalLogName g_logThreadName("main");
|
||||
|
||||
string dev::getThreadName()
|
||||
{
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
char buffer[128];
|
||||
pthread_getname_np(pthread_self(), buffer, 127);
|
||||
buffer[127] = 0;
|
||||
return buffer;
|
||||
#else
|
||||
return ThreadLocalLogName::name ? ThreadLocalLogName::name : "<unknown>";
|
||||
#endif
|
||||
}
|
||||
|
||||
void dev::setThreadName(char const* _n)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
pthread_setname_np(pthread_self(), _n);
|
||||
#elif defined(__APPLE__)
|
||||
pthread_setname_np(_n);
|
||||
#else
|
||||
ThreadLocalLogName::name = _n;
|
||||
#endif
|
||||
}
|
||||
|
||||
void dev::simpleDebugOut(std::string const& _s)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::ostream& os = g_logStdout ? std::cout : std::clog;
|
||||
if (!g_logNoColor)
|
||||
{
|
||||
os << _s + '\n';
|
||||
os.flush();
|
||||
return;
|
||||
}
|
||||
bool skip = false;
|
||||
std::stringstream ss;
|
||||
for (auto it : _s)
|
||||
{
|
||||
if (!skip && it == '\x1b')
|
||||
skip = true;
|
||||
else if (skip && it == 'm')
|
||||
skip = false;
|
||||
else if (!skip)
|
||||
ss << it;
|
||||
}
|
||||
ss << '\n';
|
||||
os << ss.str();
|
||||
os.flush();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
123
zano/libdevcore/Log.h
Normal file
123
zano/libdevcore/Log.h
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
This file is part of progminer.
|
||||
|
||||
progminer is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
progminer is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with progminer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** @file Log.h
|
||||
* @author Gav Wood <i@gavwood.com>
|
||||
* @date 2014
|
||||
*
|
||||
* The logging subsystem.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
|
||||
#include "Common.h"
|
||||
#include "CommonData.h"
|
||||
#include "FixedHash.h"
|
||||
#include "Terminal.h"
|
||||
#include "vector_ref.h"
|
||||
|
||||
/// The logging system's current verbosity.
|
||||
#define LOG_JSON 1
|
||||
#define LOG_PER_GPU 2
|
||||
#ifndef DEV_BUILD
|
||||
#define LOG_NEXT 4
|
||||
#else
|
||||
#define LOG_CONNECT 32
|
||||
#define LOG_SWITCH 64
|
||||
#define LOG_SUBMIT 128
|
||||
#define LOG_COMPILE 256
|
||||
#define LOG_NEXT 512
|
||||
#endif
|
||||
|
||||
extern unsigned g_logOptions;
|
||||
extern bool g_logNoColor;
|
||||
extern bool g_logSyslog;
|
||||
extern bool g_logStdout;
|
||||
|
||||
namespace dev
|
||||
{
|
||||
/// A simple log-output function that prints log messages to stdout.
|
||||
void simpleDebugOut(std::string const&);
|
||||
|
||||
/// Set the current thread's log name.
|
||||
void setThreadName(char const* _n);
|
||||
|
||||
/// Set the current thread's log name.
|
||||
std::string getThreadName();
|
||||
|
||||
/// The default logging channels. Each has an associated verbosity and three-letter prefix (name()
|
||||
/// ). Channels should inherit from LogChannel and define name() and verbosity.
|
||||
struct LogChannel
|
||||
{
|
||||
static const char* name();
|
||||
};
|
||||
struct WarnChannel : public LogChannel
|
||||
{
|
||||
static const char* name();
|
||||
};
|
||||
struct NoteChannel : public LogChannel
|
||||
{
|
||||
static const char* name();
|
||||
};
|
||||
|
||||
class LogOutputStreamBase
|
||||
{
|
||||
public:
|
||||
LogOutputStreamBase(char const* _id);
|
||||
|
||||
template <class T>
|
||||
void append(T const& _t)
|
||||
{
|
||||
m_sstr << _t;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::stringstream m_sstr; ///< The accrued log entry.
|
||||
};
|
||||
|
||||
/// Logging class, iostream-like, that can be shifted to.
|
||||
template <class Id>
|
||||
class LogOutputStream : LogOutputStreamBase
|
||||
{
|
||||
public:
|
||||
/// Construct a new object.
|
||||
/// If _term is true the the prefix info is terminated with a ']' character; if not it ends only
|
||||
/// with a '|' character.
|
||||
LogOutputStream() : LogOutputStreamBase(Id::name()) {}
|
||||
|
||||
/// Destructor. Posts the accrued log entry to the g_logPost function.
|
||||
~LogOutputStream() { simpleDebugOut(m_sstr.str()); }
|
||||
|
||||
/// Shift arbitrary data to the log. Spaces will be added between items as required.
|
||||
template <class T>
|
||||
LogOutputStream& operator<<(T const& _t)
|
||||
{
|
||||
append(_t);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
#define clog(X) dev::LogOutputStream<X>()
|
||||
|
||||
// Simple cout-like stream objects for accessing common log channels.
|
||||
// Dirties the global namespace, but oh so convenient...
|
||||
#define cnote clog(dev::NoteChannel)
|
||||
#define cwarn clog(dev::WarnChannel)
|
||||
|
||||
} // namespace dev
|
||||
74
zano/libdevcore/Terminal.h
Normal file
74
zano/libdevcore/Terminal.h
Normal file
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
namespace dev
|
||||
{
|
||||
namespace con
|
||||
{
|
||||
#define EthReset "\x1b[0m" // Text Reset
|
||||
|
||||
// Regular Colors
|
||||
#define EthBlack "\x1b[30m" // Black
|
||||
#define EthCoal "\x1b[90m" // Black
|
||||
#define EthGray "\x1b[37m" // White
|
||||
#define EthWhite "\x1b[97m" // White
|
||||
#define EthMaroon "\x1b[31m" // Red
|
||||
#define EthRed "\x1b[91m" // Red
|
||||
#define EthGreen "\x1b[32m" // Green
|
||||
#define EthLime "\x1b[92m" // Green
|
||||
#define EthOrange "\x1b[33m" // Yellow
|
||||
#define EthYellow "\x1b[93m" // Yellow
|
||||
#define EthNavy "\x1b[34m" // Blue
|
||||
#define EthBlue "\x1b[94m" // Blue
|
||||
#define EthViolet "\x1b[35m" // Purple
|
||||
#define EthPurple "\x1b[95m" // Purple
|
||||
#define EthTeal "\x1b[36m" // Cyan
|
||||
#define EthCyan "\x1b[96m" // Cyan
|
||||
|
||||
#define EthBlackBold "\x1b[1;30m" // Black
|
||||
#define EthCoalBold "\x1b[1;90m" // Black
|
||||
#define EthGrayBold "\x1b[1;37m" // White
|
||||
#define EthWhiteBold "\x1b[1;97m" // White
|
||||
#define EthMaroonBold "\x1b[1;31m" // Red
|
||||
#define EthRedBold "\x1b[1;91m" // Red
|
||||
#define EthGreenBold "\x1b[1;32m" // Green
|
||||
#define EthLimeBold "\x1b[1;92m" // Green
|
||||
#define EthOrangeBold "\x1b[1;33m" // Yellow
|
||||
#define EthYellowBold "\x1b[1;93m" // Yellow
|
||||
#define EthNavyBold "\x1b[1;34m" // Blue
|
||||
#define EthBlueBold "\x1b[1;94m" // Blue
|
||||
#define EthVioletBold "\x1b[1;35m" // Purple
|
||||
#define EthPurpleBold "\x1b[1;95m" // Purple
|
||||
#define EthTealBold "\x1b[1;36m" // Cyan
|
||||
#define EthCyanBold "\x1b[1;96m" // Cyan
|
||||
|
||||
// Background
|
||||
#define EthOnBlack "\x1b[40m" // Black
|
||||
#define EthOnCoal "\x1b[100m" // Black
|
||||
#define EthOnGray "\x1b[47m" // White
|
||||
#define EthOnWhite "\x1b[107m" // White
|
||||
#define EthOnMaroon "\x1b[41m" // Red
|
||||
#define EthOnRed "\x1b[101m" // Red
|
||||
#define EthOnGreen "\x1b[42m" // Green
|
||||
#define EthOnLime "\x1b[102m" // Green
|
||||
#define EthOnOrange "\x1b[43m" // Yellow
|
||||
#define EthOnYellow "\x1b[103m" // Yellow
|
||||
#define EthOnNavy "\x1b[44m" // Blue
|
||||
#define EthOnBlue "\x1b[104m" // Blue
|
||||
#define EthOnViolet "\x1b[45m" // Purple
|
||||
#define EthOnPurple "\x1b[105m" // Purple
|
||||
#define EthOnTeal "\x1b[46m" // Cyan
|
||||
#define EthOnCyan "\x1b[106m" // Cyan
|
||||
|
||||
// Underline
|
||||
#define EthBlackUnder "\x1b[4;30m" // Black
|
||||
#define EthGrayUnder "\x1b[4;37m" // White
|
||||
#define EthMaroonUnder "\x1b[4;31m" // Red
|
||||
#define EthGreenUnder "\x1b[4;32m" // Green
|
||||
#define EthOrangeUnder "\x1b[4;33m" // Yellow
|
||||
#define EthNavyUnder "\x1b[4;34m" // Blue
|
||||
#define EthVioletUnder "\x1b[4;35m" // Purple
|
||||
#define EthTealUnder "\x1b[4;36m" // Cyan
|
||||
|
||||
} // namespace con
|
||||
|
||||
} // namespace dev
|
||||
120
zano/libdevcore/Worker.cpp
Normal file
120
zano/libdevcore/Worker.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
This file is part of progminer.
|
||||
|
||||
progminer is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
progminer is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with progminer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** @file Worker.cpp
|
||||
* @author Gav Wood <i@gavwood.com>
|
||||
* @date 2014
|
||||
*/
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#include "Log.h"
|
||||
#include "Worker.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace dev;
|
||||
|
||||
void Worker::startWorking()
|
||||
{
|
||||
// cnote << "startWorking for thread" << m_name;
|
||||
Guard l(x_work);
|
||||
if (m_work)
|
||||
{
|
||||
WorkerState ex = WorkerState::Stopped;
|
||||
m_state.compare_exchange_weak(ex, WorkerState::Starting, std::memory_order_relaxed);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_state = WorkerState::Starting;
|
||||
m_work.reset(new thread([&]() {
|
||||
setThreadName(m_name.c_str());
|
||||
// cnote << "Thread begins";
|
||||
while (m_state != WorkerState::Killing)
|
||||
{
|
||||
WorkerState ex = WorkerState::Starting;
|
||||
bool ok = m_state.compare_exchange_weak(
|
||||
ex, WorkerState::Started, std::memory_order_relaxed);
|
||||
// cnote << "Trying to set Started: Thread was" << (unsigned)ex << "; "
|
||||
//<< ok;
|
||||
(void)ok;
|
||||
|
||||
try
|
||||
{
|
||||
workLoop();
|
||||
}
|
||||
catch (std::exception const& _e)
|
||||
{
|
||||
clog(WarnChannel) << "Exception thrown in Worker thread: " << _e.what();
|
||||
if (g_exitOnError)
|
||||
{
|
||||
clog(WarnChannel) << "Terminating due to --exit";
|
||||
raise(SIGTERM);
|
||||
}
|
||||
}
|
||||
|
||||
// ex = WorkerState::Stopping;
|
||||
// m_state.compare_exchange_weak(ex, WorkerState::Stopped,
|
||||
// std::memory_order_relaxed));
|
||||
|
||||
ex = m_state.exchange(WorkerState::Stopped);
|
||||
// cnote << "State: Stopped: Thread was" << (unsigned)ex;
|
||||
if (ex == WorkerState::Killing || ex == WorkerState::Starting)
|
||||
m_state.exchange(ex);
|
||||
|
||||
while (m_state == WorkerState::Stopped)
|
||||
this_thread::sleep_for(chrono::milliseconds(20));
|
||||
}
|
||||
}));
|
||||
// cnote << "Spawning" << m_name;
|
||||
}
|
||||
while (m_state == WorkerState::Starting)
|
||||
this_thread::sleep_for(chrono::microseconds(20));
|
||||
}
|
||||
|
||||
void Worker::triggerStopWorking()
|
||||
{
|
||||
DEV_GUARDED(x_work)
|
||||
if (m_work)
|
||||
{
|
||||
WorkerState ex = WorkerState::Started;
|
||||
m_state.compare_exchange_weak(ex, WorkerState::Stopping, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
void Worker::stopWorking()
|
||||
{
|
||||
DEV_GUARDED(x_work)
|
||||
if (m_work)
|
||||
{
|
||||
WorkerState ex = WorkerState::Started;
|
||||
m_state.compare_exchange_weak(ex, WorkerState::Stopping, std::memory_order_relaxed);
|
||||
|
||||
while (m_state != WorkerState::Stopped)
|
||||
this_thread::sleep_for(chrono::microseconds(20));
|
||||
}
|
||||
}
|
||||
|
||||
Worker::~Worker()
|
||||
{
|
||||
DEV_GUARDED(x_work)
|
||||
if (m_work)
|
||||
{
|
||||
m_state.exchange(WorkerState::Killing);
|
||||
m_work->join();
|
||||
m_work.reset();
|
||||
}
|
||||
}
|
||||
79
zano/libdevcore/Worker.h
Normal file
79
zano/libdevcore/Worker.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
This file is part of progminer.
|
||||
|
||||
progminer is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
progminer is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with progminer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** @file Worker.h
|
||||
* @author Gav Wood <i@gavwood.com>
|
||||
* @date 2014
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <signal.h>
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include "Guards.h"
|
||||
|
||||
extern bool g_exitOnError;
|
||||
|
||||
namespace dev
|
||||
{
|
||||
enum class WorkerState
|
||||
{
|
||||
Starting,
|
||||
Started,
|
||||
Stopping,
|
||||
Stopped,
|
||||
Killing
|
||||
};
|
||||
|
||||
class Worker
|
||||
{
|
||||
public:
|
||||
Worker(std::string _name) : m_name(std::move(_name)) {}
|
||||
|
||||
Worker(Worker const&) = delete;
|
||||
Worker& operator=(Worker const&) = delete;
|
||||
|
||||
virtual ~Worker();
|
||||
|
||||
/// Starts worker thread; causes startedWorking() to be called.
|
||||
void startWorking();
|
||||
|
||||
/// Triggers worker thread it should stop
|
||||
void triggerStopWorking();
|
||||
|
||||
/// Stop worker thread; causes call to stopWorking() and waits till thread has stopped.
|
||||
void stopWorking();
|
||||
|
||||
/// Whether or not this worker should stop
|
||||
bool shouldStop() const { return m_state != WorkerState::Started; }
|
||||
|
||||
std::string name() { return m_name; }
|
||||
|
||||
private:
|
||||
virtual void workLoop() = 0;
|
||||
|
||||
std::string m_name;
|
||||
|
||||
mutable Mutex x_work; ///< Lock for the network existence.
|
||||
std::unique_ptr<std::thread> m_work; ///< The network thread.
|
||||
std::atomic<WorkerState> m_state = {WorkerState::Starting};
|
||||
};
|
||||
|
||||
} // namespace dev
|
||||
225
zano/libdevcore/vector_ref.h
Normal file
225
zano/libdevcore/vector_ref.h
Normal file
@@ -0,0 +1,225 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
namespace dev
|
||||
{
|
||||
/**
|
||||
* A modifiable reference to an existing object or vector in memory.
|
||||
*/
|
||||
template <class _T>
|
||||
class vector_ref
|
||||
{
|
||||
public:
|
||||
using value_type = _T;
|
||||
using element_type = _T;
|
||||
using mutable_value_type = typename std::conditional<std::is_const<_T>::value,
|
||||
typename std::remove_const<_T>::type, _T>::type;
|
||||
|
||||
static_assert(std::is_pod<value_type>::value,
|
||||
"vector_ref can only be used with PODs due to its low-level treatment of data.");
|
||||
|
||||
vector_ref() : m_data(nullptr), m_count(0) {}
|
||||
/// Creates a new vector_ref to point to @a _count elements starting at @a _data.
|
||||
vector_ref(_T* _data, size_t _count) : m_data(_data), m_count(_count) {}
|
||||
/// Creates a new vector_ref pointing to the data part of a string (given as pointer).
|
||||
vector_ref(
|
||||
typename std::conditional<std::is_const<_T>::value, std::string const*, std::string*>::type
|
||||
_data)
|
||||
: m_data(reinterpret_cast<_T*>(_data->data())), m_count(_data->size() / sizeof(_T))
|
||||
{}
|
||||
/// Creates a new vector_ref pointing to the data part of a vector (given as pointer).
|
||||
vector_ref(typename std::conditional<std::is_const<_T>::value,
|
||||
std::vector<typename std::remove_const<_T>::type> const*, std::vector<_T>*>::type _data)
|
||||
: m_data(_data->data()), m_count(_data->size())
|
||||
{}
|
||||
/// Creates a new vector_ref pointing to the data part of a string (given as reference).
|
||||
vector_ref(
|
||||
typename std::conditional<std::is_const<_T>::value, std::string const&, std::string&>::type
|
||||
_data)
|
||||
: m_data(reinterpret_cast<_T*>(_data.data())), m_count(_data.size() / sizeof(_T))
|
||||
{}
|
||||
#if DEV_LDB
|
||||
vector_ref(ldb::Slice const& _s)
|
||||
: m_data(reinterpret_cast<_T*>(_s.data())), m_count(_s.size() / sizeof(_T))
|
||||
{}
|
||||
#endif
|
||||
explicit operator bool() const { return m_data && m_count; }
|
||||
|
||||
bool contentsEqual(std::vector<mutable_value_type> const& _c) const
|
||||
{
|
||||
if (!m_data || m_count == 0)
|
||||
return _c.empty();
|
||||
return _c.size() == m_count && !memcmp(_c.data(), m_data, m_count * sizeof(_T));
|
||||
}
|
||||
std::vector<mutable_value_type> toVector() const
|
||||
{
|
||||
return std::vector<mutable_value_type>(m_data, m_data + m_count);
|
||||
}
|
||||
std::vector<unsigned char> toBytes() const
|
||||
{
|
||||
return std::vector<unsigned char>(reinterpret_cast<unsigned char const*>(m_data),
|
||||
reinterpret_cast<unsigned char const*>(m_data) + m_count * sizeof(_T));
|
||||
}
|
||||
std::string toString() const
|
||||
{
|
||||
return std::string((char const*)m_data, ((char const*)m_data) + m_count * sizeof(_T));
|
||||
}
|
||||
|
||||
template <class _T2>
|
||||
explicit operator vector_ref<_T2>() const
|
||||
{
|
||||
assert(m_count * sizeof(_T) / sizeof(_T2) * sizeof(_T2) / sizeof(_T) == m_count);
|
||||
return vector_ref<_T2>(reinterpret_cast<_T2*>(m_data), m_count * sizeof(_T) / sizeof(_T2));
|
||||
}
|
||||
operator vector_ref<_T const>() const { return vector_ref<_T const>(m_data, m_count); }
|
||||
|
||||
_T* data() const { return m_data; }
|
||||
/// @returns the number of elements referenced (not necessarily number of bytes).
|
||||
size_t count() const { return m_count; }
|
||||
/// @returns the number of elements referenced (not necessarily number of bytes).
|
||||
size_t size() const { return m_count; }
|
||||
bool empty() const { return !m_count; }
|
||||
/// @returns a new vector_ref pointing at the next chunk of @a size() elements.
|
||||
vector_ref<_T> next() const
|
||||
{
|
||||
if (!m_data)
|
||||
return *this;
|
||||
return vector_ref<_T>(m_data + m_count, m_count);
|
||||
}
|
||||
/// @returns a new vector_ref which is a shifted and shortened view of the original data.
|
||||
/// If this goes out of bounds in any way, returns an empty vector_ref.
|
||||
/// If @a _count is ~size_t(0), extends the view to the end of the data.
|
||||
vector_ref<_T> cropped(size_t _begin, size_t _count) const
|
||||
{
|
||||
if (m_data && _begin <= m_count && _count <= m_count && _begin + _count <= m_count)
|
||||
return vector_ref<_T>(
|
||||
m_data + _begin, _count == ~size_t(0) ? m_count - _begin : _count);
|
||||
return {};
|
||||
}
|
||||
/// @returns a new vector_ref which is a shifted view of the original data (not going beyond
|
||||
/// it).
|
||||
vector_ref<_T> cropped(size_t _begin) const
|
||||
{
|
||||
if (m_data && _begin <= m_count)
|
||||
return vector_ref<_T>(m_data + _begin, m_count - _begin);
|
||||
return {};
|
||||
}
|
||||
void retarget(_T* _d, size_t _s)
|
||||
{
|
||||
m_data = _d;
|
||||
m_count = _s;
|
||||
}
|
||||
void retarget(std::vector<_T> const& _t)
|
||||
{
|
||||
m_data = _t.data();
|
||||
m_count = _t.size();
|
||||
}
|
||||
template <class T>
|
||||
bool overlapsWith(vector_ref<T> _t) const
|
||||
{
|
||||
void const* f1 = data();
|
||||
void const* t1 = data() + size();
|
||||
void const* f2 = _t.data();
|
||||
void const* t2 = _t.data() + _t.size();
|
||||
return f1 < t2 && t1 > f2;
|
||||
}
|
||||
/// Copies the contents of this vector_ref to the contents of @a _t, up to the max size of @a
|
||||
/// _t.
|
||||
void copyTo(vector_ref<typename std::remove_const<_T>::type> _t) const
|
||||
{
|
||||
if (overlapsWith(_t))
|
||||
memmove(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T));
|
||||
else
|
||||
memcpy(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T));
|
||||
}
|
||||
/// Copies the contents of this vector_ref to the contents of @a _t, and zeros further trailing
|
||||
/// elements in @a _t.
|
||||
void populate(vector_ref<typename std::remove_const<_T>::type> _t) const
|
||||
{
|
||||
copyTo(_t);
|
||||
memset(_t.data() + m_count, 0, std::max(_t.size(), m_count) - m_count);
|
||||
}
|
||||
/// Securely overwrite the memory.
|
||||
/// @note adapted from OpenSSL's implementation.
|
||||
void cleanse()
|
||||
{
|
||||
static unsigned char s_cleanseCounter = 0;
|
||||
auto* p = (uint8_t*)begin();
|
||||
size_t const len = (uint8_t*)end() - p;
|
||||
size_t loop = len;
|
||||
size_t count = s_cleanseCounter;
|
||||
while (loop--)
|
||||
{
|
||||
*(p++) = (uint8_t)count;
|
||||
count += (17 + ((size_t)p & 0xf));
|
||||
}
|
||||
p = (uint8_t*)memchr((uint8_t*)begin(), (uint8_t)count, len);
|
||||
if (p)
|
||||
count += (63 + (size_t)p);
|
||||
s_cleanseCounter = (uint8_t)count;
|
||||
memset((uint8_t*)begin(), 0, len);
|
||||
}
|
||||
|
||||
_T* begin() { return m_data; }
|
||||
_T* end() { return m_data + m_count; }
|
||||
_T const* begin() const { return m_data; }
|
||||
_T const* end() const { return m_data + m_count; }
|
||||
|
||||
_T& operator[](size_t _i)
|
||||
{
|
||||
assert(m_data);
|
||||
assert(_i < m_count);
|
||||
return m_data[_i];
|
||||
}
|
||||
_T const& operator[](size_t _i) const
|
||||
{
|
||||
assert(m_data);
|
||||
assert(_i < m_count);
|
||||
return m_data[_i];
|
||||
}
|
||||
|
||||
bool operator==(vector_ref<_T> const& _cmp) const
|
||||
{
|
||||
return m_data == _cmp.m_data && m_count == _cmp.m_count;
|
||||
}
|
||||
bool operator!=(vector_ref<_T> const& _cmp) const { return !operator==(_cmp); }
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_data = nullptr;
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
_T* m_data;
|
||||
size_t m_count;
|
||||
};
|
||||
|
||||
template <class _T>
|
||||
vector_ref<_T const> ref(_T const& _t)
|
||||
{
|
||||
return vector_ref<_T const>(&_t, 1);
|
||||
}
|
||||
template <class _T>
|
||||
vector_ref<_T> ref(_T& _t)
|
||||
{
|
||||
return vector_ref<_T>(&_t, 1);
|
||||
}
|
||||
template <class _T>
|
||||
vector_ref<_T const> ref(std::vector<_T> const& _t)
|
||||
{
|
||||
return vector_ref<_T const>(&_t);
|
||||
}
|
||||
template <class _T>
|
||||
vector_ref<_T> ref(std::vector<_T>& _t)
|
||||
{
|
||||
return vector_ref<_T>(&_t);
|
||||
}
|
||||
|
||||
} // namespace dev
|
||||
Reference in New Issue
Block a user