Replace fc::uint128 with boost::multiprecision::uint128_t
This commit is contained in:
parent
648d969fb9
commit
a3e2410091
16 changed files with 207 additions and 607 deletions
|
|
@ -194,7 +194,7 @@ set( CMAKE_FIND_LIBRARY_SUFFIXES ${ORIGINAL_LIB_SUFFIXES} )
|
|||
option( UNITY_BUILD OFF )
|
||||
|
||||
set( fc_sources
|
||||
src/uint128.cpp
|
||||
src/popcount.cpp
|
||||
src/variant.cpp
|
||||
src/exception.cpp
|
||||
src/variant_object.cpp
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
#pragma once
|
||||
#include <fc/io/raw_fwd.hpp>
|
||||
|
||||
#include <fc/crypto/sha512.hpp>
|
||||
#include <fc/crypto/sha256.hpp>
|
||||
#include <fc/uint128.hpp>
|
||||
#include <fc/fwd.hpp>
|
||||
#include <fc/uint128.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace fc {
|
||||
|
|
@ -15,9 +16,8 @@ namespace fc {
|
|||
aes_encoder();
|
||||
~aes_encoder();
|
||||
|
||||
void init( const fc::sha256& key, const fc::uint128& init_value );
|
||||
void init( const fc::sha256& key, const uint128_t& init_value );
|
||||
uint32_t encode( const char* plaintxt, uint32_t len, char* ciphertxt );
|
||||
// uint32_t final_encode( char* ciphertxt );
|
||||
|
||||
private:
|
||||
struct impl;
|
||||
|
|
@ -29,9 +29,8 @@ namespace fc {
|
|||
aes_decoder();
|
||||
~aes_decoder();
|
||||
|
||||
void init( const fc::sha256& key, const fc::uint128& init_value );
|
||||
void init( const fc::sha256& key, const uint128_t& init_value );
|
||||
uint32_t decode( const char* ciphertxt, uint32_t len, char* plaintext );
|
||||
// uint32_t final_decode( char* plaintext );
|
||||
|
||||
private:
|
||||
struct impl;
|
||||
|
|
|
|||
|
|
@ -41,36 +41,25 @@
|
|||
// doesn't hold for any hash functions in this file.
|
||||
#pragma once
|
||||
|
||||
#include <fc/uint128.hpp>
|
||||
|
||||
#include <stdlib.h> // for size_t.
|
||||
#include <stdint.h>
|
||||
#include <utility>
|
||||
|
||||
namespace fc {
|
||||
|
||||
template<typename T, size_t N>
|
||||
class array;
|
||||
class uint128;
|
||||
|
||||
// Hash function for a byte array.
|
||||
uint64_t city_hash64(const char *buf, size_t len);
|
||||
|
||||
uint32_t city_hash32(const char *buf, size_t len);
|
||||
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
inline size_t city_hash_size_t(const char *buf, size_t len) { return city_hash64(buf, len); }
|
||||
#else
|
||||
uint32_t city_hash32(const char *buf, size_t len);
|
||||
inline size_t city_hash_size_t(const char *buf, size_t len) { return city_hash32(buf, len); }
|
||||
#endif
|
||||
|
||||
// Hash function for a byte array.
|
||||
uint128 city_hash128(const char *s, size_t len);
|
||||
|
||||
// Hash function for a byte array.
|
||||
uint64_t city_hash_crc_64(const char *buf, size_t len);
|
||||
|
||||
// Hash function for a byte array.
|
||||
uint128 city_hash_crc_128(const char *s, size_t len);
|
||||
array<uint64_t,4> city_hash_crc_256(const char *s, size_t len);
|
||||
|
||||
uint128_t city_hash_crc_128(const char *s, size_t len);
|
||||
|
||||
} // namespace fc
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include <boost/endian/buffers.hpp>
|
||||
#include <fc/io/raw_fwd.hpp>
|
||||
#include <fc/fwd.hpp>
|
||||
|
||||
namespace fc
|
||||
|
|
@ -9,16 +10,16 @@ class sha512
|
|||
{
|
||||
public:
|
||||
sha512();
|
||||
explicit sha512( const string& hex_str );
|
||||
explicit sha512( const std::string& hex_str );
|
||||
|
||||
string str()const;
|
||||
operator string()const;
|
||||
std::string str()const;
|
||||
operator std::string()const;
|
||||
|
||||
char* data()const;
|
||||
size_t data_size()const { return 512 / 8; }
|
||||
|
||||
static sha512 hash( const char* d, uint32_t dlen );
|
||||
static sha512 hash( const string& );
|
||||
static sha512 hash( const std::string& );
|
||||
|
||||
template<typename T>
|
||||
static sha512 hash( const T& t )
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include <boost/endian/buffers.hpp>
|
||||
|
||||
#include <fc/io/raw_variant.hpp>
|
||||
#include <fc/reflect/reflect.hpp>
|
||||
#include <fc/io/datastream.hpp>
|
||||
|
|
@ -24,6 +25,24 @@ namespace fc {
|
|||
pack( s, args..., _max_depth );
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
inline void pack( Stream& s, const uint128_t& v, uint32_t _max_depth )
|
||||
{
|
||||
boost::endian::little_uint64_buf_at hilo[2];
|
||||
hilo[0] = static_cast<uint64_t>(v >> 64);
|
||||
hilo[1] = static_cast<uint64_t>(v & 0xffffffffffffffffULL);
|
||||
s.write( hilo[0].data(), sizeof(hilo) );
|
||||
}
|
||||
template<typename Stream>
|
||||
inline void unpack( Stream& s, uint128_t& v, uint32_t _max_depth )
|
||||
{
|
||||
boost::endian::little_uint64_buf_at hilo[2];
|
||||
s.read( (char*) hilo, sizeof(hilo) );
|
||||
v = hilo[0].value();
|
||||
v <<= 64;
|
||||
v += hilo[1].value();
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
inline void pack( Stream& s, const fc::exception& e, uint32_t _max_depth )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
#pragma once
|
||||
#include <boost/endian/buffers.hpp>
|
||||
|
||||
#include <fc/config.hpp>
|
||||
#include <fc/container/flat_fwd.hpp>
|
||||
#include <fc/io/varint.hpp>
|
||||
#include <fc/array.hpp>
|
||||
#include <fc/safe.hpp>
|
||||
#include <fc/uint128.hpp>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
|
@ -42,7 +44,10 @@ namespace fc {
|
|||
template<typename Stream, typename IntType, typename EnumType>
|
||||
inline void unpack( Stream& s, fc::enum_type<IntType,EnumType>& tp, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
|
||||
|
||||
|
||||
template<typename Stream>
|
||||
inline void pack( Stream& s, const uint128_t& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
|
||||
template<typename Stream>
|
||||
inline void unpack( Stream& s, uint128_t& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
|
||||
|
||||
template<typename Stream, typename T> inline void pack( Stream& s, const std::set<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
|
||||
template<typename Stream, typename T> inline void unpack( Stream& s, std::set<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
|
||||
|
|
|
|||
40
include/fc/popcount.hpp
Normal file
40
include/fc/popcount.hpp
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2019 BitShares Blockchain Foundation, and contributors.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fc/platform_independence.hpp>
|
||||
#include <fc/uint128.hpp>
|
||||
|
||||
namespace fc {
|
||||
|
||||
#if _MSC_VER || __GNUC__ || __clang__
|
||||
inline uint8_t popcount( uint64_t v ) { return __builtin_popcountll(v); }
|
||||
#else
|
||||
uint8_t popcount( uint64_t v );
|
||||
#endif
|
||||
|
||||
uint8_t popcount( const fc::uint128_t& v );
|
||||
|
||||
} // namespace fc
|
||||
|
|
@ -11,8 +11,7 @@ namespace fc {
|
|||
* integer overflow and default initialization. It will
|
||||
* throw an exception on overflow conditions.
|
||||
*
|
||||
* It can only be used on built-in types. In particular,
|
||||
* safe<uint128_t> is buggy and should not be used.
|
||||
* It can only be used on built-in types.
|
||||
*
|
||||
* Implemented using spec from:
|
||||
* https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
|
||||
|
|
|
|||
|
|
@ -1,158 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2019 BitShares Blockchain Foundation, and contributors.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <limits>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
#include <fc/config.hpp>
|
||||
#include <fc/exception/exception.hpp>
|
||||
#include <fc/crypto/city.hpp>
|
||||
#include <fc/io/raw.hpp>
|
||||
#include <boost/multiprecision/integer.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable : 4244)
|
||||
#endif //// _MSC_VER
|
||||
namespace fc {
|
||||
|
||||
namespace fc
|
||||
{
|
||||
class bigint;
|
||||
/**
|
||||
* @brief an implementation of 128 bit unsigned integer
|
||||
*
|
||||
*/
|
||||
class uint128
|
||||
{
|
||||
|
||||
|
||||
public:
|
||||
uint128():hi(0),lo(0){}
|
||||
uint128( uint32_t l ):hi(0),lo(l){}
|
||||
uint128( int32_t l ):hi( -(l<0) ),lo(l){}
|
||||
uint128( int64_t l ):hi( -(l<0) ),lo(l){}
|
||||
uint128( uint64_t l ):hi(0),lo(l){}
|
||||
uint128( const std::string& s );
|
||||
uint128( uint64_t _h, uint64_t _l )
|
||||
:hi(_h),lo(_l){}
|
||||
uint128( const fc::bigint& bi );
|
||||
|
||||
operator std::string()const;
|
||||
operator fc::bigint()const;
|
||||
|
||||
bool operator == ( const uint128& o )const{ return hi == o.hi && lo == o.lo; }
|
||||
bool operator != ( const uint128& o )const{ return hi != o.hi || lo != o.lo; }
|
||||
bool operator < ( const uint128& o )const { return (hi == o.hi) ? lo < o.lo : hi < o.hi; }
|
||||
bool operator < ( const int64_t& o )const { return *this < uint128(o); }
|
||||
bool operator !()const { return !(hi !=0 || lo != 0); }
|
||||
uint128 operator -()const { return ++uint128( ~hi, ~lo ); }
|
||||
uint128 operator ~()const { return uint128( ~hi, ~lo ); }
|
||||
|
||||
uint128& operator++() { hi += (++lo == 0); return *this; }
|
||||
uint128& operator--() { hi -= (lo-- == 0); return *this; }
|
||||
uint128 operator++(int) { auto tmp = *this; ++(*this); return tmp; }
|
||||
uint128 operator--(int) { auto tmp = *this; --(*this); return tmp; }
|
||||
|
||||
uint128& operator |= ( const uint128& u ) { hi |= u.hi; lo |= u.lo; return *this; }
|
||||
uint128& operator &= ( const uint128& u ) { hi &= u.hi; lo &= u.lo; return *this; }
|
||||
uint128& operator ^= ( const uint128& u ) { hi ^= u.hi; lo ^= u.lo; return *this; }
|
||||
uint128& operator <<= ( const uint128& u );
|
||||
uint128& operator >>= ( const uint128& u );
|
||||
|
||||
uint128& operator += ( const uint128& u ) { const uint64_t old = lo; lo += u.lo; hi += u.hi + (lo < old); return *this; }
|
||||
uint128& operator -= ( const uint128& u ) { return *this += -u; }
|
||||
uint128& operator *= ( const uint128& u );
|
||||
uint128& operator /= ( const uint128& u );
|
||||
uint128& operator %= ( const uint128& u );
|
||||
|
||||
|
||||
friend uint128 operator + ( const uint128& l, const uint128& r ) { return uint128(l)+=r; }
|
||||
friend uint128 operator - ( const uint128& l, const uint128& r ) { return uint128(l)-=r; }
|
||||
friend uint128 operator * ( const uint128& l, const uint128& r ) { return uint128(l)*=r; }
|
||||
friend uint128 operator / ( const uint128& l, const uint128& r ) { return uint128(l)/=r; }
|
||||
friend uint128 operator % ( const uint128& l, const uint128& r ) { return uint128(l)%=r; }
|
||||
friend uint128 operator | ( const uint128& l, const uint128& r ) { return uint128(l)=(r); }
|
||||
friend uint128 operator & ( const uint128& l, const uint128& r ) { return uint128(l)&=r; }
|
||||
friend uint128 operator ^ ( const uint128& l, const uint128& r ) { return uint128(l)^=r; }
|
||||
friend uint128 operator << ( const uint128& l, const uint128& r ) { return uint128(l)<<=r; }
|
||||
friend uint128 operator >> ( const uint128& l, const uint128& r ) { return uint128(l)>>=r; }
|
||||
friend bool operator > ( const uint128& l, const uint128& r ) { return r < l; }
|
||||
friend bool operator > ( const uint128& l, const int64_t& r ) { return uint128(r) < l; }
|
||||
friend bool operator > ( const int64_t& l, const uint128& r ) { return r < uint128(l); }
|
||||
|
||||
friend bool operator >= ( const uint128& l, const uint128& r ) { return l == r || l > r; }
|
||||
friend bool operator >= ( const uint128& l, const int64_t& r ) { return l >= uint128(r); }
|
||||
friend bool operator >= ( const int64_t& l, const uint128& r ) { return uint128(l) >= r; }
|
||||
friend bool operator <= ( const uint128& l, const uint128& r ) { return l == r || l < r; }
|
||||
friend bool operator <= ( const uint128& l, const int64_t& r ) { return l <= uint128(r); }
|
||||
friend bool operator <= ( const int64_t& l, const uint128& r ) { return uint128(l) <= r; }
|
||||
|
||||
friend std::size_t hash_value( const uint128& v ) { return city_hash_size_t((const char*)&v, sizeof(v)); }
|
||||
|
||||
uint32_t to_integer()const
|
||||
{
|
||||
FC_ASSERT( hi == 0 );
|
||||
uint32_t lo32 = (uint32_t) lo;
|
||||
FC_ASSERT( lo == lo32 );
|
||||
return lo32;
|
||||
}
|
||||
uint64_t to_uint64()const
|
||||
{
|
||||
FC_ASSERT( hi == 0 );
|
||||
return lo;
|
||||
}
|
||||
uint32_t low_32_bits()const { return (uint32_t) lo; }
|
||||
uint64_t low_bits()const { return lo; }
|
||||
uint64_t high_bits()const { return hi; }
|
||||
|
||||
static uint128 max_value() {
|
||||
const uint64_t max64 = std::numeric_limits<uint64_t>::max();
|
||||
return uint128( max64, max64 );
|
||||
}
|
||||
|
||||
static void full_product( const uint128& a, const uint128& b, uint128& result_hi, uint128& result_lo );
|
||||
|
||||
uint8_t popcount() const;
|
||||
|
||||
// fields must be public for serialization
|
||||
uint64_t hi;
|
||||
uint64_t lo;
|
||||
};
|
||||
static_assert( sizeof(uint128) == 2*sizeof(uint64_t), "validate packing assumptions" );
|
||||
|
||||
typedef uint128 uint128_t;
|
||||
|
||||
class variant;
|
||||
|
||||
void to_variant( const uint128& var, variant& vo, uint32_t max_depth = 1 );
|
||||
void from_variant( const variant& var, uint128& vo, uint32_t max_depth = 1 );
|
||||
|
||||
namespace raw
|
||||
{
|
||||
template<typename Stream>
|
||||
inline void pack( Stream& s, const uint128& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) {
|
||||
pack( s, u.hi, _max_depth );
|
||||
pack( s, u.lo, _max_depth );
|
||||
}
|
||||
template<typename Stream>
|
||||
inline void unpack( Stream& s, uint128& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) {
|
||||
unpack( s, u.hi, _max_depth );
|
||||
unpack( s, u.lo, _max_depth );
|
||||
}
|
||||
}
|
||||
|
||||
size_t city_hash_size_t(const char *buf, size_t len);
|
||||
using boost::multiprecision::uint128_t;
|
||||
|
||||
} // namespace fc
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
struct hash<fc::uint128>
|
||||
{
|
||||
size_t operator()( const fc::uint128& s )const;
|
||||
};
|
||||
}
|
||||
|
||||
FC_REFLECT( fc::uint128_t, (hi)(lo) )
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif ///_MSC_VER
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <cstdlib>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4482) // nonstandard extension used enum Name::Val, standard in C++11
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <string.h> // memset
|
||||
|
||||
#include <fc/optional.hpp>
|
||||
#include <fc/uint128.hpp>
|
||||
#include <fc/container/flat_fwd.hpp>
|
||||
#include <boost/endian/buffers.hpp>
|
||||
#include <boost/multi_index_container_fwd.hpp>
|
||||
|
|
@ -146,6 +147,9 @@ namespace fc
|
|||
void to_variant( const microseconds& input_microseconds, variant& output_variant, uint32_t max_depth );
|
||||
void from_variant( const variant& input_variant, microseconds& output_microseconds, uint32_t max_depth );
|
||||
|
||||
void to_variant( const uint128_t& var, variant& vo, uint32_t max_depth = 1 );
|
||||
void from_variant( const variant& var, uint128_t& vo, uint32_t max_depth = 1 );
|
||||
|
||||
#ifdef __APPLE__
|
||||
void to_variant( size_t s, variant& v, uint32_t max_depth = 1 );
|
||||
#elif !defined(_MSC_VER)
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@
|
|||
#include <fc/fwd_impl.hpp>
|
||||
|
||||
#include <fc/io/fstream.hpp>
|
||||
#include <fc/io/raw.hpp>
|
||||
|
||||
#include <fc/log/logger.hpp>
|
||||
|
||||
#include <fc/thread/thread.hpp>
|
||||
#include <fc/io/raw.hpp>
|
||||
#include <boost/endian/buffers.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <openssl/opensslconf.h>
|
||||
|
|
@ -38,7 +38,7 @@ aes_encoder::~aes_encoder()
|
|||
{
|
||||
}
|
||||
|
||||
void aes_encoder::init( const fc::sha256& key, const fc::uint128& init_value )
|
||||
void aes_encoder::init( const fc::sha256& key, const uint128_t& init_value )
|
||||
{
|
||||
my->ctx.obj = EVP_CIPHER_CTX_new();
|
||||
/* Create and initialise the context */
|
||||
|
|
@ -54,8 +54,8 @@ void aes_encoder::init( const fc::sha256& key, const fc::uint128& init_value )
|
|||
* IV size for *most* modes is the same as the block size. For AES this
|
||||
* is 128 bits */
|
||||
boost::endian::little_uint64_buf_t iv[2];
|
||||
iv[0] = init_value.hi;
|
||||
iv[1] = init_value.lo;
|
||||
iv[0] = static_cast<uint64_t>( init_value >> 64 );
|
||||
iv[1] = static_cast<uint64_t>( init_value & 0xffffffffffffffffULL );
|
||||
if(1 != EVP_EncryptInit_ex(my->ctx, EVP_aes_256_cbc(), NULL, (unsigned char*)&key, (const unsigned char*)iv[0].data()))
|
||||
{
|
||||
FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc encryption init",
|
||||
|
|
@ -106,7 +106,7 @@ aes_decoder::aes_decoder()
|
|||
(void)init;
|
||||
}
|
||||
|
||||
void aes_decoder::init( const fc::sha256& key, const fc::uint128& init_value )
|
||||
void aes_decoder::init( const fc::sha256& key, const uint128_t& init_value )
|
||||
{
|
||||
my->ctx.obj = EVP_CIPHER_CTX_new();
|
||||
/* Create and initialise the context */
|
||||
|
|
@ -122,8 +122,8 @@ void aes_decoder::init( const fc::sha256& key, const fc::uint128& init_value )
|
|||
* IV size for *most* modes is the same as the block size. For AES this
|
||||
* is 128 bits */
|
||||
boost::endian::little_uint64_buf_t iv[2];
|
||||
iv[0] = init_value.hi;
|
||||
iv[1] = init_value.lo;
|
||||
iv[0] = static_cast<uint64_t>( init_value >> 64 );
|
||||
iv[1] = static_cast<uint64_t>( init_value & 0xffffffffffffffffULL );
|
||||
if(1 != EVP_DecryptInit_ex(my->ctx, EVP_aes_256_cbc(), NULL, (unsigned char*)&key, (const unsigned char*)iv[0].data()))
|
||||
{
|
||||
FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc encryption init",
|
||||
|
|
|
|||
|
|
@ -33,8 +33,6 @@
|
|||
#include <algorithm>
|
||||
#include <string.h> // for memcpy and memset
|
||||
#include <fc/crypto/city.hpp>
|
||||
#include <fc/uint128.hpp>
|
||||
#include <fc/array.hpp>
|
||||
#include <boost/endian/buffers.hpp>
|
||||
|
||||
#if defined(__SSE4_2__) && defined(__x86_64__)
|
||||
|
|
@ -47,13 +45,16 @@ namespace fc {
|
|||
|
||||
using namespace std;
|
||||
|
||||
|
||||
inline uint64_t Uint128Low64(const uint128& x) { return x.low_bits(); }
|
||||
inline uint64_t Uint128High64(const uint128& x) { return x.high_bits(); }
|
||||
inline uint64_t Uint128Low64(const uint128_t& x) {
|
||||
return static_cast<uint64_t>(x & 0xffffffffffffffffULL);
|
||||
}
|
||||
inline uint64_t Uint128High64(const uint128_t& x) {
|
||||
return static_cast<uint64_t>( x >> 64 );
|
||||
}
|
||||
|
||||
// Hash 128 input bits down to 64 bits of output.
|
||||
// This is intended to be a reasonably good hash function.
|
||||
inline uint64_t Hash128to64(const uint128& x) {
|
||||
inline uint64_t Hash128to64(const uint128_t& x) {
|
||||
// Murmur-inspired hashing.
|
||||
const uint64_t kMul = 0x9ddfea08eb382d69ULL;
|
||||
uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul;
|
||||
|
|
@ -280,7 +281,7 @@ static uint64_t ShiftMix(uint64_t val) {
|
|||
}
|
||||
|
||||
static uint64_t HashLen16(uint64_t u, uint64_t v) {
|
||||
return Hash128to64(uint128(u, v));
|
||||
return Hash128to64( ( uint128_t(u) << 64 ) + v);
|
||||
}
|
||||
|
||||
static uint64_t HashLen16(uint64_t u, uint64_t v, uint64_t mul) {
|
||||
|
|
@ -425,7 +426,7 @@ uint64_t CityHash64WithSeed(const char *s, size_t len, uint64_t seed) {
|
|||
|
||||
// A subroutine for CityHash128(). Returns a decent 128-bit hash for strings
|
||||
// of any length representable in signed long. Based on City and Murmur.
|
||||
static uint128 CityMurmur(const char *s, size_t len, uint128 seed) {
|
||||
uint128_t CityMurmur(const char *s, size_t len, uint128_t seed) {
|
||||
uint64_t a = Uint128Low64(seed);
|
||||
uint64_t b = Uint128High64(seed);
|
||||
uint64_t c = 0;
|
||||
|
|
@ -452,10 +453,10 @@ static uint128 CityMurmur(const char *s, size_t len, uint128 seed) {
|
|||
}
|
||||
a = HashLen16(a, c);
|
||||
b = HashLen16(d, b);
|
||||
return uint128(a ^ b, HashLen16(b, a));
|
||||
return ( uint128_t(a ^ b) << 64 ) + HashLen16(b, a);
|
||||
}
|
||||
|
||||
uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) {
|
||||
uint128_t CityHash128WithSeed(const char *s, size_t len, uint128_t seed) {
|
||||
if (len < 128) {
|
||||
return CityMurmur(s, len, seed);
|
||||
}
|
||||
|
|
@ -514,15 +515,15 @@ uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) {
|
|||
// different 56-byte-to-8-byte hashes to get a 16-byte final result.
|
||||
x = HashLen16(x, v.first);
|
||||
y = HashLen16(y + z, w.first);
|
||||
return uint128(HashLen16(x + v.second, w.second) + y,
|
||||
HashLen16(x + w.second, y + v.second));
|
||||
return ( uint128_t( HashLen16(x + v.second, w.second) + y ) << 64 )
|
||||
+ HashLen16(x + w.second, y + v.second);
|
||||
}
|
||||
|
||||
uint128 city_hash128(const char *s, size_t len) {
|
||||
uint128_t city_hash128(const char *s, size_t len) {
|
||||
return len >= 16 ?
|
||||
CityHash128WithSeed(s + 16, len - 16,
|
||||
uint128(Fetch64(s), Fetch64(s + 8) + k0)) :
|
||||
CityHash128WithSeed(s, len, uint128(k0, k1));
|
||||
( uint128_t( Fetch64(s) ) << 64 ) + Fetch64(s + 8) + k0) :
|
||||
CityHash128WithSeed(s, len, ( uint128_t(k0) << 64 ) + k1);
|
||||
}
|
||||
|
||||
//#ifdef __SSE4_2__
|
||||
|
|
@ -640,7 +641,7 @@ array<uint64_t,4> city_hash_crc_256(const char *s, size_t len)
|
|||
return buf;
|
||||
}
|
||||
|
||||
uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed) {
|
||||
uint128_t CityHashCrc128WithSeed(const char *s, size_t len, uint128_t seed) {
|
||||
if (len <= 900) {
|
||||
return CityHash128WithSeed(s, len, seed);
|
||||
} else {
|
||||
|
|
@ -648,18 +649,18 @@ uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed) {
|
|||
CityHashCrc256(s, len, result);
|
||||
uint64_t u = Uint128High64(seed) + result[0];
|
||||
uint64_t v = Uint128Low64(seed) + result[1];
|
||||
return uint128(HashLen16(u, v + result[2]),
|
||||
HashLen16(Rotate(v, 32), u * k0 + result[3]));
|
||||
return ( uint128_t( HashLen16(u, v + result[2]) ) << 64 )
|
||||
+ HashLen16(Rotate(v, 32), u * k0 + result[3]);
|
||||
}
|
||||
}
|
||||
|
||||
uint128 city_hash_crc_128(const char *s, size_t len) {
|
||||
uint128_t city_hash_crc_128(const char *s, size_t len) {
|
||||
if (len <= 900) {
|
||||
return city_hash128(s, len);
|
||||
} else {
|
||||
uint64_t result[4];
|
||||
CityHashCrc256(s, len, result);
|
||||
return uint128(result[2], result[3]);
|
||||
return ( uint128_t(result[2]) << 64 ) + result[3];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
54
src/popcount.cpp
Normal file
54
src/popcount.cpp
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (c) 2019 BitShares Blockchain Foundation, and contributors.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <fc/popcount.hpp>
|
||||
|
||||
namespace fc {
|
||||
|
||||
#if _MSC_VER || __GNUC__ || __clang__
|
||||
#else
|
||||
uint8_t popcount( uint64_t v )
|
||||
{
|
||||
// Public Domain code taken from http://graphics.stanford.edu/~seander/bithacks.html
|
||||
uint8_t c;
|
||||
static const int S[] = {1, 2, 4, 8, 16, 32};
|
||||
static const uint64_t B[] = {0x5555555555555555, 0x3333333333333333, 0x0F0F0F0F0F0F0F0F,
|
||||
0x00FF00FF00FF00FF, 0x0000FFFF0000FFFF, 0x00000000FFFFFFFF };
|
||||
|
||||
c = v - ((v >> 1) & B[0]);
|
||||
c = ((c >> S[1]) & B[1]) + (c & B[1]);
|
||||
c = ((c >> S[2]) + c) & B[2];
|
||||
c = ((c >> S[3]) + c) & B[3];
|
||||
c = ((c >> S[4]) + c) & B[4];
|
||||
return ((c >> S[5]) + c) & B[5];
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t popcount( const uint128_t& v )
|
||||
{
|
||||
return popcount( static_cast<uint64_t>(v >> 64) )
|
||||
+ popcount( static_cast<uint64_t>(v & 0xffffffffffffffffULL) );
|
||||
}
|
||||
|
||||
} // namespace fc
|
||||
398
src/uint128.cpp
398
src/uint128.cpp
|
|
@ -1,398 +0,0 @@
|
|||
#include <fc/uint128.hpp>
|
||||
#include <fc/variant.hpp>
|
||||
#include <fc/crypto/bigint.hpp>
|
||||
#include <boost/endian/buffers.hpp>
|
||||
#include <boost/multiprecision/cpp_int.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace fc
|
||||
{
|
||||
typedef boost::multiprecision::uint128_t m128;
|
||||
|
||||
template <typename T>
|
||||
static void divide(const T &numerator, const T &denominator, T "ient, T &remainder)
|
||||
{
|
||||
static const int bits = sizeof(T) * 8;
|
||||
|
||||
if(denominator == 0) {
|
||||
throw std::domain_error("divide by zero");
|
||||
} else {
|
||||
T n = numerator;
|
||||
T d = denominator;
|
||||
T x = 1;
|
||||
T answer = 0;
|
||||
|
||||
|
||||
while((n >= d) && (((d >> (bits - 1)) & 1) == 0)) {
|
||||
x <<= 1;
|
||||
d <<= 1;
|
||||
}
|
||||
|
||||
while(x != 0) {
|
||||
if(n >= d) {
|
||||
n -= d;
|
||||
answer |= x;
|
||||
}
|
||||
|
||||
x >>= 1;
|
||||
d >>= 1;
|
||||
}
|
||||
|
||||
quotient = answer;
|
||||
remainder = n;
|
||||
}
|
||||
}
|
||||
|
||||
uint128::uint128(const std::string &sz)
|
||||
:hi(0), lo(0)
|
||||
{
|
||||
// do we have at least one character?
|
||||
if(!sz.empty()) {
|
||||
// make some reasonable assumptions
|
||||
int radix = 10;
|
||||
bool minus = false;
|
||||
|
||||
std::string::const_iterator i = sz.begin();
|
||||
|
||||
// check for minus sign, i suppose technically this should only apply
|
||||
// to base 10, but who says that -0x1 should be invalid?
|
||||
if(*i == '-') {
|
||||
++i;
|
||||
minus = true;
|
||||
}
|
||||
|
||||
// check if there is radix changing prefix (0 or 0x)
|
||||
if(i != sz.end()) {
|
||||
if(*i == '0') {
|
||||
radix = 8;
|
||||
++i;
|
||||
if(i != sz.end()) {
|
||||
if(*i == 'x') {
|
||||
radix = 16;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while(i != sz.end()) {
|
||||
unsigned int n = 0;
|
||||
const char ch = *i;
|
||||
|
||||
if(ch >= 'A' && ch <= 'Z') {
|
||||
if(((ch - 'A') + 10) < radix) {
|
||||
n = (ch - 'A') + 10;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else if(ch >= 'a' && ch <= 'z') {
|
||||
if(((ch - 'a') + 10) < radix) {
|
||||
n = (ch - 'a') + 10;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else if(ch >= '0' && ch <= '9') {
|
||||
if((ch - '0') < radix) {
|
||||
n = (ch - '0');
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* completely invalid character */
|
||||
break;
|
||||
}
|
||||
|
||||
(*this) *= radix;
|
||||
(*this) += n;
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
// if this was a negative number, do that two's compliment madness :-P
|
||||
if(minus) {
|
||||
*this = -*this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint128::operator bigint()const
|
||||
{
|
||||
boost::endian::big_uint64_buf_t tmp[2];
|
||||
tmp[0] = hi;
|
||||
tmp[1] = lo;
|
||||
bigint bi( (char*)&tmp, sizeof(tmp) );
|
||||
return bi;
|
||||
}
|
||||
uint128::uint128( const fc::bigint& bi )
|
||||
{
|
||||
*this = uint128( std::string(bi) ); // TODO: optimize this...
|
||||
}
|
||||
|
||||
uint128::operator std::string ()const
|
||||
{
|
||||
if(*this == 0) { return "0"; }
|
||||
|
||||
// at worst it will be size digits (base 2) so make our buffer
|
||||
// that plus room for null terminator
|
||||
static char sz [128 + 1];
|
||||
sz[sizeof(sz) - 1] = '\0';
|
||||
|
||||
uint128 ii(*this);
|
||||
int i = 128 - 1;
|
||||
|
||||
while (ii != 0 && i) {
|
||||
|
||||
uint128 remainder;
|
||||
divide(ii, uint128(10), ii, remainder);
|
||||
sz [--i] = "0123456789abcdefghijklmnopqrstuvwxyz"[remainder.to_integer()];
|
||||
}
|
||||
|
||||
return &sz[i];
|
||||
}
|
||||
|
||||
|
||||
uint128& uint128::operator<<=(const uint128& rhs)
|
||||
{
|
||||
if(rhs >= 128)
|
||||
{
|
||||
hi = 0;
|
||||
lo = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int n = rhs.to_integer();
|
||||
const unsigned int halfsize = 128 / 2;
|
||||
|
||||
if(n >= halfsize){
|
||||
n -= halfsize;
|
||||
hi = lo;
|
||||
lo = 0;
|
||||
}
|
||||
|
||||
if(n != 0) {
|
||||
// shift high half
|
||||
hi <<= n;
|
||||
|
||||
const uint64_t mask(~(uint64_t(-1) >> n));
|
||||
|
||||
// and add them to high half
|
||||
hi |= (lo & mask) >> (halfsize - n);
|
||||
|
||||
// and finally shift also low half
|
||||
lo <<= n;
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint128 & uint128::operator>>=(const uint128& rhs)
|
||||
{
|
||||
if(rhs >= 128)
|
||||
{
|
||||
hi = 0;
|
||||
lo = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int n = rhs.to_integer();
|
||||
const unsigned int halfsize = 128 / 2;
|
||||
|
||||
if(n >= halfsize) {
|
||||
n -= halfsize;
|
||||
lo = hi;
|
||||
hi = 0;
|
||||
}
|
||||
|
||||
if(n != 0) {
|
||||
// shift low half
|
||||
lo >>= n;
|
||||
|
||||
// get lower N bits of high half
|
||||
const uint64_t mask(~(uint64_t(-1) << n));
|
||||
|
||||
// and add them to low qword
|
||||
lo |= (hi & mask) << (halfsize - n);
|
||||
|
||||
// and finally shift also high half
|
||||
hi >>= n;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint128& uint128::operator/=(const uint128 &b)
|
||||
{
|
||||
auto self = (m128(hi) << 64) + m128(lo);
|
||||
auto other = (m128(b.hi) << 64) + m128(b.lo);
|
||||
self /= other;
|
||||
hi = static_cast<uint64_t>(self >> 64);
|
||||
lo = static_cast<uint64_t>((self << 64 ) >> 64);
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint128& uint128::operator%=(const uint128 &b)
|
||||
{
|
||||
uint128 quotient;
|
||||
divide(*this, b, quotient, *this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint128& uint128::operator*=(const uint128 &b)
|
||||
{
|
||||
uint64_t a0 = (uint32_t) (this->lo );
|
||||
uint64_t a1 = (uint32_t) (this->lo >> 0x20);
|
||||
uint64_t a2 = (uint32_t) (this->hi );
|
||||
uint64_t a3 = (uint32_t) (this->hi >> 0x20);
|
||||
|
||||
uint64_t b0 = (uint32_t) (b.lo );
|
||||
uint64_t b1 = (uint32_t) (b.lo >> 0x20);
|
||||
uint64_t b2 = (uint32_t) (b.hi );
|
||||
uint64_t b3 = (uint32_t) (b.hi >> 0x20);
|
||||
|
||||
// (a0 + (a1 << 0x20) + (a2 << 0x40) + (a3 << 0x60)) *
|
||||
// (b0 + (b1 << 0x20) + (b2 << 0x40) + (b3 << 0x60)) =
|
||||
// a0 * b0
|
||||
//
|
||||
// (a1 * b0 + a0 * b1) << 0x20
|
||||
// (a2 * b0 + a1 * b1 + a0 * b2) << 0x40
|
||||
// (a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3) << 0x60
|
||||
//
|
||||
// all other cross terms are << 0x80 or higher, thus do not appear in result
|
||||
|
||||
this->hi = 0;
|
||||
this->lo = a3*b0;
|
||||
(*this) += a2*b1;
|
||||
(*this) += a1*b2;
|
||||
(*this) += a0*b3;
|
||||
(*this) <<= 0x20;
|
||||
(*this) += a2*b0;
|
||||
(*this) += a1*b1;
|
||||
(*this) += a0*b2;
|
||||
(*this) <<= 0x20;
|
||||
(*this) += a1*b0;
|
||||
(*this) += a0*b1;
|
||||
(*this) <<= 0x20;
|
||||
(*this) += a0*b0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void uint128::full_product( const uint128& a, const uint128& b, uint128& result_hi, uint128& result_lo )
|
||||
{
|
||||
// (ah * 2**64 + al) * (bh * 2**64 + bl)
|
||||
// = (ah * bh * 2**128 + al * bh * 2**64 + ah * bl * 2**64 + al * bl
|
||||
// = P * 2**128 + (Q + R) * 2**64 + S
|
||||
// = Ph * 2**192 + Pl * 2**128
|
||||
// + Qh * 2**128 + Ql * 2**64
|
||||
// + Rh * 2**128 + Rl * 2**64
|
||||
// + Sh * 2**64 + Sl
|
||||
//
|
||||
|
||||
uint64_t ah = a.hi;
|
||||
uint64_t al = a.lo;
|
||||
uint64_t bh = b.hi;
|
||||
uint64_t bl = b.lo;
|
||||
|
||||
uint128 s = al;
|
||||
s *= bl;
|
||||
uint128 r = ah;
|
||||
r *= bl;
|
||||
uint128 q = al;
|
||||
q *= bh;
|
||||
uint128 p = ah;
|
||||
p *= bh;
|
||||
|
||||
uint64_t sl = s.lo;
|
||||
uint64_t sh = s.hi;
|
||||
uint64_t rl = r.lo;
|
||||
uint64_t rh = r.hi;
|
||||
uint64_t ql = q.lo;
|
||||
uint64_t qh = q.hi;
|
||||
uint64_t pl = p.lo;
|
||||
uint64_t ph = p.hi;
|
||||
|
||||
uint64_t y[4]; // final result
|
||||
y[0] = sl;
|
||||
|
||||
uint128_t acc = sh;
|
||||
acc += ql;
|
||||
acc += rl;
|
||||
y[1] = acc.lo;
|
||||
acc = acc.hi;
|
||||
acc += qh;
|
||||
acc += rh;
|
||||
acc += pl;
|
||||
y[2] = acc.lo;
|
||||
y[3] = acc.hi + ph;
|
||||
|
||||
result_hi = uint128( y[3], y[2] );
|
||||
result_lo = uint128( y[1], y[0] );
|
||||
}
|
||||
|
||||
static uint8_t _popcount_64( uint64_t x )
|
||||
{
|
||||
static const uint64_t m[] = {
|
||||
0x5555555555555555ULL,
|
||||
0x3333333333333333ULL,
|
||||
0x0F0F0F0F0F0F0F0FULL,
|
||||
0x00FF00FF00FF00FFULL,
|
||||
0x0000FFFF0000FFFFULL,
|
||||
0x00000000FFFFFFFFULL
|
||||
};
|
||||
// TODO future optimization: replace slow, portable version
|
||||
// with fast, non-portable __builtin_popcountll intrinsic
|
||||
// (when available)
|
||||
|
||||
for( int i=0, w=1; i<6; i++, w+=w )
|
||||
{
|
||||
x = (x & m[i]) + ((x >> w) & m[i]);
|
||||
}
|
||||
return uint8_t(x);
|
||||
}
|
||||
|
||||
uint8_t uint128::popcount()const
|
||||
{
|
||||
return _popcount_64( lo ) + _popcount_64( hi );
|
||||
}
|
||||
|
||||
void to_variant( const uint128& var, variant& vo, uint32_t max_depth )
|
||||
{
|
||||
vo = std::string(var);
|
||||
}
|
||||
void from_variant( const variant& var, uint128& vo, uint32_t max_depth )
|
||||
{
|
||||
vo = uint128(var.as_string());
|
||||
}
|
||||
|
||||
} // namespace fc
|
||||
|
||||
namespace std {
|
||||
size_t hash<fc::uint128>::operator()( const fc::uint128& s )const
|
||||
{
|
||||
boost::endian::little_uint64_buf_t tmp[2];
|
||||
tmp[0] = s.hi;
|
||||
tmp[1] = s.lo;
|
||||
return fc::city_hash_size_t((char*)&tmp, sizeof(tmp));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Portions of the above code were adapted from the work of Evan Teran.
|
||||
*
|
||||
* Copyright (c) 2008
|
||||
* Evan Teran
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted, provided
|
||||
* that the above copyright notice appears in all copies and that both the
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the same name not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. We make no representations about the
|
||||
* suitability this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*/
|
||||
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
namespace fc
|
||||
{
|
||||
|
||||
/**
|
||||
* The TypeID is stored in the 'last byte' of the variant.
|
||||
*/
|
||||
|
|
@ -672,6 +673,16 @@ void from_variant( const variant& var, std::vector<char>& vo, uint32_t max_depth
|
|||
}
|
||||
}
|
||||
|
||||
void to_variant( const uint128_t& var, variant& vo, uint32_t max_depth )
|
||||
{
|
||||
vo = var.str();
|
||||
}
|
||||
|
||||
void from_variant( const variant& var, uint128_t& vo, uint32_t max_depth )
|
||||
{
|
||||
vo = uint128_t( var.as_string() );
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
#elif !defined(_MSC_VER)
|
||||
void to_variant( long long int s, variant& v, uint32_t max_depth ) { v = variant( int64_t(s) ); }
|
||||
|
|
|
|||
Loading…
Reference in a new issue