From 747567fbdc2e34bd2632bfe7d1c97ce988aeea2c Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Thu, 17 Sep 2020 12:24:52 -0500 Subject: [PATCH] Revert "Removed signed_int" This reverts commit 1dcacbafc9e85552e8bd9b8b5082e1ce3364fe43. --- include/fc/io/raw.hpp | 21 ++++++++++++++++ include/fc/io/raw_fwd.hpp | 3 +++ include/fc/io/varint.hpp | 43 +++++++++++++++++++++++++++++++++ include/fc/reflect/typename.hpp | 2 ++ src/io/varint.cpp | 2 ++ 5 files changed, 71 insertions(+) diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index 2b96f1e..7a4b7d0 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -192,6 +192,16 @@ namespace fc { v = std::make_shared(std::move(tmp)); } FC_RETHROW_EXCEPTIONS( warn, "std::shared_ptr", ("type",fc::get_typename::name()) ) } + template inline void pack( Stream& s, const signed_int& v, uint32_t _max_depth ) { + uint32_t val = (v.value<<1) ^ (v.value>>31); + do { + uint8_t b = uint8_t(val) & 0x7f; + val >>= 7; + b |= ((val > 0) << 7); + s.write((char*)&b,1);//.put(b); + } while( val ); + } + template inline void pack( Stream& s, const unsigned_int& v, uint32_t _max_depth ) { uint64_t val = v.value; do { @@ -202,6 +212,17 @@ namespace fc { }while( val ); } + template inline void unpack( Stream& s, signed_int& vi, uint32_t _max_depth ) { + uint32_t v = 0; char b = 0; int by = 0; + do { + s.get(b); + v |= uint32_t(uint8_t(b) & 0x7f) << by; + by += 7; + } while( (uint8_t(b) & 0x80) && by < 32 ); + vi.value = ((v>>1) ^ (v>>31)) + (v&0x01); + vi.value = v&0x01 ? vi.value : -vi.value; + vi.value = -vi.value; + } template inline void unpack( Stream& s, unsigned_int& vi, uint32_t _max_depth ) { uint64_t v = 0; char b = 0; uint8_t by = 0; do { diff --git a/include/fc/io/raw_fwd.hpp b/include/fc/io/raw_fwd.hpp index e82fe44..9897f07 100644 --- a/include/fc/io/raw_fwd.hpp +++ b/include/fc/io/raw_fwd.hpp @@ -119,6 +119,9 @@ namespace fc { template inline void pack( Stream& s, const std::vector& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); template inline void unpack( Stream& s, std::vector& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void pack( Stream& s, const signed_int& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void unpack( Stream& s, signed_int& vi, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template inline void pack( Stream& s, const unsigned_int& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); template inline void unpack( Stream& s, unsigned_int& vi, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); diff --git a/include/fc/io/varint.hpp b/include/fc/io/varint.hpp index 2b58ee2..66bb35c 100644 --- a/include/fc/io/varint.hpp +++ b/include/fc/io/varint.hpp @@ -41,8 +41,42 @@ struct unsigned_int { friend bool operator>=( const unsigned_int& i, const unsigned_int& v ) { return i.value >= v.value; } }; +/** + * @brief serializes a 32 bit signed interger in as few bytes as possible + * + * Uses the google protobuf algorithm for seralizing signed numbers + */ +struct signed_int { + signed_int( int32_t v = 0 ):value(v){} + operator int32_t()const { return value; } + template + signed_int& operator=( const T& v ) { value = v; return *this; } + signed_int operator++(int) { return value++; } + signed_int& operator++(){ ++value; return *this; } + + int32_t value; + + friend bool operator==( const signed_int& i, const int32_t& v ) { return i.value == v; } + friend bool operator==( const int32_t& i, const signed_int& v ) { return i == v.value; } + friend bool operator==( const signed_int& i, const signed_int& v ) { return i.value == v.value; } + + friend bool operator!=( const signed_int& i, const int32_t& v ) { return i.value != v; } + friend bool operator!=( const int32_t& i, const signed_int& v ) { return i != v.value; } + friend bool operator!=( const signed_int& i, const signed_int& v ) { return i.value != v.value; } + + friend bool operator<( const signed_int& i, const int32_t& v ) { return i.value < v; } + friend bool operator<( const int32_t& i, const signed_int& v ) { return i < v.value; } + friend bool operator<( const signed_int& i, const signed_int& v ) { return i.value < v.value; } + + friend bool operator>=( const signed_int& i, const int32_t& v ) { return i.value >= v; } + friend bool operator>=( const int32_t& i, const signed_int& v ) { return i >= v.value; } + friend bool operator>=( const signed_int& i, const signed_int& v ) { return i.value >= v.value; } +}; + class variant; +void to_variant( const signed_int& var, variant& vo, uint32_t max_depth = 1 ); +void from_variant( const variant& var, signed_int& vo, uint32_t max_depth = 1 ); void to_variant( const unsigned_int& var, variant& vo, uint32_t max_depth = 1 ); void from_variant( const variant& var, unsigned_int& vo, uint32_t max_depth = 1 ); @@ -51,6 +85,15 @@ void from_variant( const variant& var, unsigned_int& vo, uint32_t max_depth = 1 #include namespace std { + template<> + struct hash + { + public: + size_t operator()(const fc::signed_int &a) const + { + return std::hash()(a.value); + } + }; template<> struct hash { diff --git a/include/fc/reflect/typename.hpp b/include/fc/reflect/typename.hpp index 23a116b..ce2abfb 100644 --- a/include/fc/reflect/typename.hpp +++ b/include/fc/reflect/typename.hpp @@ -132,8 +132,10 @@ namespace fc { } }; + struct signed_int; struct unsigned_int; class variant_object; + template<> struct get_typename { static const char* name() { return "signed_int"; } }; template<> struct get_typename { static const char* name() { return "unsigned_int"; } }; template<> struct get_typename { static const char* name() { return "fc::variant_object"; } }; diff --git a/src/io/varint.cpp b/src/io/varint.cpp index a5c6bbb..6384eec 100644 --- a/src/io/varint.cpp +++ b/src/io/varint.cpp @@ -3,6 +3,8 @@ namespace fc { +void to_variant( const signed_int& var, variant& vo, uint32_t max_depth ) { vo = var.value; } +void from_variant( const variant& var, signed_int& vo, uint32_t max_depth ) { vo.value = static_cast(var.as_int64()); } void to_variant( const unsigned_int& var, variant& vo, uint32_t max_depth ) { vo = var.value; } void from_variant( const variant& var, unsigned_int& vo, uint32_t max_depth ) { vo.value = var.as_uint64(); } }