From 90203c9b86ac97a40d574c376cf184f8b60f74d7 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sun, 19 Jul 2020 19:58:17 -0700 Subject: [PATCH] truncate when storing scalar numeric --- src/data.cpp | 38 +++++++++++++++++++++++++++++++++++--- test/testdata.cpp | 31 ++++++++++++++++++++++++++++++- test/testtype.cpp | 28 +++++++++++++++++++++++++++- 3 files changed, 92 insertions(+), 5 deletions(-) diff --git a/src/data.cpp b/src/data.cpp index 5c477d8..4486fdf 100644 --- a/src/data.cpp +++ b/src/data.cpp @@ -512,9 +512,41 @@ void Value::copyIn(const void *ptr, StoreType type) throw NoField(); switch(store->code) { - case StoreType::Real: if(!copyInScalar(store->as(), ptr, type)) throw NoConvert(); break; - case StoreType::Integer: if(!copyInScalar(store->as(), ptr, type)) throw NoConvert(); break; - case StoreType::UInteger: if(!copyInScalar(store->as(), ptr, type)) throw NoConvert(); break; + case StoreType::Real: { + if(!copyInScalar(store->as(), ptr, type)) throw NoConvert(); + // truncate as if assigned to narrower type + if(desc->code==TypeCode::Float32) + store->as() = float(store->as()); + break; + } + case StoreType::Integer: { + if(!copyInScalar(store->as(), ptr, type)) throw NoConvert(); + // truncate as if assigned to narrower type + int64_t orig = store->as(); + switch(desc->code.code) { + case TypeCode::Int8: orig = int8_t(orig); break; + case TypeCode::Int16: orig = int16_t(orig); break; + case TypeCode::Int32: orig = int32_t(orig); break; + case TypeCode::Int64: orig = int64_t(orig); break; + default: break; + } + store->as() = orig; + break; + } + case StoreType::UInteger: { + if(!copyInScalar(store->as(), ptr, type)) throw NoConvert(); + // truncate as if assigned to narrower type + int64_t orig = store->as(); + switch(desc->code.code) { + case TypeCode::UInt8: orig = uint8_t(orig); break; + case TypeCode::UInt16: orig = uint16_t(orig); break; + case TypeCode::UInt32: orig = uint32_t(orig); break; + case TypeCode::UInt64: orig = uint64_t(orig); break; + default: break; + } + store->as() = orig; + break; + } case StoreType::Bool: { auto& dest = store->as(); switch(type) { diff --git a/test/testdata.cpp b/test/testdata.cpp index a6ba262..6c8c24d 100644 --- a/test/testdata.cpp +++ b/test/testdata.cpp @@ -273,6 +273,26 @@ void testConvertScalar(const Store& store, const Inout& inout) testEq(inout, cont.as())<"< +void testConvertScalar2(const Store& store, const In& in, const Out& out) +{ + testShow()<<__func__<<"("< store_t; + + auto cont = TypeDef(store_t::code).create(); + + try { + cont.from(in); + }catch(std::exception& e){ + testCase(false)<<"Error storing as "<())<())<"<(1.0, true); testConvertScalar(0.0, false); testConvertScalar(5.0, 5); @@ -365,6 +386,10 @@ MAIN(testdata) testConvertScalar(-5, -5); testConvertScalar(-5, -5.0); testConvertScalar(-5, "-5"); + testConvertScalar(0xffffffff, -1); + testConvertScalar(0xffffffff, -1); + testConvertScalar(0xffff, 0xffff); + testConvertScalar(0x80000000, -2147483648); testConvertScalar("true", true); testConvertScalar("false", false); testConvertScalar("5", 5); @@ -372,6 +397,10 @@ MAIN(testdata) testConvertScalar("-5", -5); testConvertScalar("-5", -5.0); testConvertScalar("-5", "-5"); + + testConvertScalar2(-2147483648, 0x80000000, -2147483648); + testConvertScalar2(0, 0x100000000llu, -0); + testAssignSimilar(); cleanup_for_valgrind(); return testDone(); diff --git a/test/testtype.cpp b/test/testtype.cpp index 3db8373..59dc406 100644 --- a/test/testtype.cpp +++ b/test/testtype.cpp @@ -28,6 +28,31 @@ void showSize() #undef CASE } +void testCode() +{ + testDiag("%s()", __func__); + + testEq(TypeCode{TypeCode::UInt8}.size(), 1u); + testEq(TypeCode{TypeCode::UInt16}.size(), 2u); + testEq(TypeCode{TypeCode::UInt32}.size(), 4u); + testEq(TypeCode{TypeCode::UInt64}.size(), 8u); + + testEq(TypeCode{TypeCode::UInt8A}.size(), 1u); + testEq(TypeCode{TypeCode::UInt16A}.size(), 2u); + testEq(TypeCode{TypeCode::UInt32A}.size(), 4u); + testEq(TypeCode{TypeCode::UInt64A}.size(), 8u); + + testEq(TypeCode{TypeCode::Int8}.size(), 1u); + testEq(TypeCode{TypeCode::Int16}.size(), 2u); + testEq(TypeCode{TypeCode::Int32}.size(), 4u); + testEq(TypeCode{TypeCode::Int64}.size(), 8u); + + testEq(TypeCode{TypeCode::Int8A}.size(), 1u); + testEq(TypeCode{TypeCode::Int16A}.size(), 2u); + testEq(TypeCode{TypeCode::Int32A}.size(), 4u); + testEq(TypeCode{TypeCode::Int64A}.size(), 8u); +} + void testBasic() { testDiag("%s()", __func__); @@ -460,9 +485,10 @@ void testFormat() MAIN(testtype) { - testPlan(29); + testPlan(45); testSetup(); showSize(); + testCode(); testBasic(); testTypeDef(); testTypeDefDynamic();