From d7917b9c348de3a83eee9d1850974a66cc6b4b1b Mon Sep 17 00:00:00 2001 From: Steven Strand Date: Fri, 1 Feb 2019 16:02:46 -0500 Subject: [PATCH] fix issue #400 extract signed_int from datastream --- libraries/eosiolib/varint.hpp | 11 ++++------- tests/CMakeLists.txt | 1 + tests/unit/CMakeLists.txt | 1 + tests/unit/varint_tests.cpp | 28 ++++++++++++++++++++++++++++ 4 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 tests/unit/varint_tests.cpp diff --git a/libraries/eosiolib/varint.hpp b/libraries/eosiolib/varint.hpp index a89cb5dde41..57966442d83 100644 --- a/libraries/eosiolib/varint.hpp +++ b/libraries/eosiolib/varint.hpp @@ -4,7 +4,6 @@ */ #pragma once - /** * @defgroup varint Variable Length Integer Type * @brief Defines variable length integer type which provides more efficient serialization @@ -406,8 +405,8 @@ struct signed_int { */ template friend DataStream& operator << ( DataStream& ds, const signed_int& v ){ - uint32_t val = uint32_t((v.value<<1) ^ (v.value>>31)); - do { + uint32_t val = uint32_t((v.value<<1) ^ (v.value>>31)); //apply zigzag encoding + do { //store 7 bit chunks uint8_t b = uint8_t(val) & 0x7f; val >>= 7; b |= ((val > 0) << 7); @@ -427,14 +426,12 @@ struct signed_int { template friend DataStream& operator >> ( DataStream& ds, signed_int& vi ){ uint32_t v = 0; char b = 0; int by = 0; - do { + do { //read 7 bit chunks ds.get(b); v |= uint32_t(uint8_t(b) & 0x7f) << by; by += 7; } while( uint8_t(b) & 0x80 ); - vi.value = ((v>>1) ^ (v>>31)) + (v&0x01); - vi.value = v&0x01 ? vi.value : -vi.value; - vi.value = -vi.value; + vi.value= (v>>1) ^ -(v&1); //reverse zigzag encoding return ds; } }; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b03ec429296..3e9c5a4db66 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,6 +2,7 @@ add_test(name_tests ${CMAKE_BINARY_DIR}/tests/unit/name_tests) add_test(rope_tests ${CMAKE_BINARY_DIR}/tests/unit/rope_tests) add_test(print_tests ${CMAKE_BINARY_DIR}/tests/unit/print_tests) add_test(system_tests ${CMAKE_BINARY_DIR}/tests/unit/system_tests) +add_test(varint_tests ${CMAKE_BINARY_DIR}/tests/unit/varint_tests) if (eosio_FOUND) add_test(integration_tests ${CMAKE_BINARY_DIR}/tests/integration/integration_tests) endif() diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 3ea8443c893..6d46ab565c4 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -5,5 +5,6 @@ add_native_executable(name_tests name_tests.cpp) add_native_executable(system_tests system_tests.cpp) add_native_executable(rope_tests rope_tests.cpp) add_native_executable(print_tests print_tests.cpp) +add_native_executable(varint_tests varint_tests.cpp) add_subdirectory(test_contracts) diff --git a/tests/unit/varint_tests.cpp b/tests/unit/varint_tests.cpp new file mode 100644 index 00000000000..8868e7cb51c --- /dev/null +++ b/tests/unit/varint_tests.cpp @@ -0,0 +1,28 @@ +#include +#include + +using namespace eosio::native; +using namespace eosio; + +EOSIO_TEST_BEGIN(signed_int_test) //test datastream insert/extract signed_int + //silence_output(true); + + char buffer[32]; + datastream ds(buffer,32); + signed_int a(44), b((1<<30)+2), c(-35), d(-(1<<30)-2); //small +, small -, large +, large - + ds << a << b << c << d; + ds.seekp(0); + signed_int aa, bb, cc, dd; + ds >> aa >> bb >> cc >> dd; + char* errmess= "signed_int datastream extract fails"; + check(a.value==aa.value,errmess); + check(b.value==bb.value,errmess); + check(c.value==cc.value,errmess); + check(d.value==dd.value,errmess); + silence_output(false); +EOSIO_TEST_END + +int main(int argc, char** argv) { + EOSIO_TEST(signed_int_test); + return has_failed(); +}