diff --git a/src/data.cpp b/src/data.cpp index 3d31be1..1445f23 100644 --- a/src/data.cpp +++ b/src/data.cpp @@ -115,6 +115,7 @@ Value& Value::assign(const Value& o) switch(dstore->code) { case StoreType::Real: + case StoreType::Bool: case StoreType::Integer: case StoreType::UInteger: dstore->as() = sstore->as(); @@ -145,6 +146,7 @@ Value& Value::assign(const Value& o) switch(dstore->code) { case StoreType::Real: + case StoreType::Bool: case StoreType::Integer: case StoreType::UInteger: dstore->as() = sstore->as(); @@ -315,6 +317,7 @@ bool copyOutScalar(const Src& src, void *ptr, StoreType type) case StoreType::Real: *reinterpret_cast(ptr) = src; return true; case StoreType::Integer: *reinterpret_cast(ptr) = src; return true; case StoreType::UInteger: *reinterpret_cast(ptr) = src; return true; + case StoreType::Bool: *reinterpret_cast(ptr) = src; return true; case StoreType::String: *reinterpret_cast(ptr) = SB()<as(), ptr, type)) return; else break; case StoreType::Integer: if(copyOutScalar(store->as(), ptr, type)) return; else break; case StoreType::UInteger: if(copyOutScalar(store->as(), ptr, type)) return; else break; + case StoreType::Bool: { + auto& src = store->as(); + + switch(type) { + case StoreType::Bool: *reinterpret_cast(ptr) = src; return; + case StoreType::Integer: + case StoreType::UInteger: *reinterpret_cast(ptr) = src; return; + case StoreType::Real: *reinterpret_cast(ptr) = src; return; + case StoreType::String: *reinterpret_cast(ptr) = src ? "true" : "false"; return; + default: + break; + } + break; + } case StoreType::String: { auto& src = store->as(); switch(type) { case StoreType::String: *reinterpret_cast(ptr) = src; return; - // TODO: parse Integer/Real + case StoreType::Integer: { + epicsInt64 temp; + if(epicsParseInt64(src.c_str(), &temp, 0, nullptr)==0) { + *reinterpret_cast(ptr) = temp; + return; + } + } + case StoreType::UInteger: { + epicsUInt64 temp; + if(epicsParseUInt64(src.c_str(), &temp, 0, nullptr)==0) { + *reinterpret_cast(ptr) = temp; + return; + } + } + case StoreType::Real: { + double temp; + if(epicsParseDouble(src.c_str(), &temp, nullptr)==0) { + *reinterpret_cast(ptr) = temp; + return; + } + } + case StoreType::Bool: { + if(src=="true") { *reinterpret_cast(ptr) = true; return; } + else if(src=="flase") { *reinterpret_cast(ptr) = false; return; } + } default: break; } @@ -402,6 +443,7 @@ bool copyInScalar(Dest& dest, const void *ptr, StoreType type) case StoreType::Real: dest = *reinterpret_cast(ptr); return true; case StoreType::Integer: dest = *reinterpret_cast(ptr); return true; case StoreType::UInteger: dest = *reinterpret_cast(ptr); return true; + case StoreType::Bool: dest = *reinterpret_cast(ptr); return true; case StoreType::String: // TODO: parse from string case StoreType::Null: case StoreType::Compound: @@ -424,6 +466,22 @@ void Value::copyIn(const void *ptr, StoreType type) 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::Bool: { + auto& dest = store->as(); + switch(type) { + case StoreType::Bool: dest = *reinterpret_cast(ptr); break; + case StoreType::Integer: + case StoreType::UInteger: dest = 0!=*reinterpret_cast(ptr); break; + //case StoreType::Real: // TODO pick condition. strict non-zero? fabs()<0.5 ? + case StoreType::String: + if("true"==*reinterpret_cast(ptr)) { dest = true; break; } + else if("false"==*reinterpret_cast(ptr)) { dest = false; break; } + // fall through + default: + throw NoConvert(); + } + break; + } case StoreType::String: { auto& dest = store->as(); @@ -432,6 +490,7 @@ void Value::copyIn(const void *ptr, StoreType type) case StoreType::Integer: dest = SB()<<*reinterpret_cast(ptr); break; case StoreType::UInteger: dest = SB()<<*reinterpret_cast(ptr); break; case StoreType::Real: dest = SB()<<*reinterpret_cast(ptr); break; + case StoreType::Bool: dest = (*reinterpret_cast(ptr)) ? "true" : "false"; break; default: throw NoConvert(); } @@ -735,6 +794,7 @@ void show_Value(std::ostream& strm, case StoreType::Real: strm<<" = "<as()<<"\n"; break; case StoreType::Integer: strm<<" = "<as()<<"\n"; break; case StoreType::UInteger: strm<<" = "<as()<<"\n"; break; + case StoreType::Bool: strm<<" = "<<(store->as() ? "true" : "false")<<"\n"; break; case StoreType::String: strm<<" = \""<as())<<"\"\n"; break; case StoreType::Compound: { auto& fld = store->as(); @@ -810,15 +870,12 @@ void FieldStorage::init(const FieldDesc *desc) this->code = StoreType::Compound; break; case Kind::Integer: - if(!desc->code.isunsigned()) { - as() = 0u; - this->code = StoreType::Integer; - break; - } - // fall trhough - case Kind::Bool: as() = 0u; - this->code = StoreType::UInteger; + this->code = desc->code.isunsigned() ? StoreType::UInteger : StoreType::Integer; + break; + case Kind::Bool: + as() = false; + this->code = StoreType::Bool; break; case Kind::Real: as() = 0.0; @@ -837,6 +894,7 @@ void FieldStorage::deinit() case StoreType::Integer: case StoreType::UInteger: case StoreType::Real: + case StoreType::Bool: break; case StoreType::Array: as>().~shared_array(); diff --git a/src/dataencode.cpp b/src/dataencode.cpp index 6737100..bb90e4a 100644 --- a/src/dataencode.cpp +++ b/src/dataencode.cpp @@ -293,7 +293,6 @@ void to_wire_field(Buffer& buf, const FieldDesc* desc, const std::shared_ptras(); switch(desc->code.code) { - case TypeCode::Bool: to_wire(buf, uint8_t (fld!=0)); return; case TypeCode::UInt8: to_wire(buf, uint8_t (fld)); return; case TypeCode::UInt16: to_wire(buf, uint16_t(fld)); return; case TypeCode::UInt32: to_wire(buf, uint32_t(fld)); return; @@ -302,6 +301,14 @@ void to_wire_field(Buffer& buf, const FieldDesc* desc, const std::shared_ptras(); + switch(desc->code.code) { + case TypeCode::Bool: to_wire(buf, uint8_t (fld)); return; + default: break; + } + } + break; case StoreType::String: { auto& fld = store->as(); switch(desc->code.code) { @@ -508,7 +515,6 @@ void from_wire_field(Buffer& buf, TypeStore& ctxt, const FieldDesc* desc, const case StoreType::UInteger: { auto& fld = store->as(); switch(desc->code.code) { - case TypeCode::Bool: fld = 0!=from_wire_as(buf); return; case TypeCode::UInt8: fld = from_wire_as(buf); return; case TypeCode::UInt16: fld = from_wire_as(buf); return; case TypeCode::UInt32: fld = from_wire_as(buf); return; @@ -517,6 +523,14 @@ void from_wire_field(Buffer& buf, TypeStore& ctxt, const FieldDesc* desc, const } } break; + case StoreType::Bool: { + auto& fld = store->as(); + switch(desc->code.code) { + case TypeCode::Bool: fld = 0!=from_wire_as(buf); return; + default: break; + } + } + break; case StoreType::String: { auto& fld = store->as(); switch(desc->code.code) { diff --git a/src/pvxs/data.h b/src/pvxs/data.h index 5a036cb..e23fdad 100644 --- a/src/pvxs/data.h +++ b/src/pvxs/data.h @@ -23,6 +23,7 @@ class Value; //! selector for union FieldStorage::store enum struct StoreType : uint8_t { Null, //!< no associate storage + Bool, //!< bool UInteger, //!< uint64_t Integer, //!< int64_t Real, //!< double @@ -47,9 +48,9 @@ template struct StorageMap{} && std::is_signed{}>::type> { typedef int64_t store_t; static constexpr StoreType code{StoreType::Integer}; }; -// map unsigned integers, and bool, to uint64_t +// map unsigned integers to uint64_t template -struct StorageMap{} && !std::is_signed{}>::type> +struct StorageMap{} && !std::is_signed{} && !std::is_same{}>::type> { typedef uint64_t store_t; static constexpr StoreType code{StoreType::UInteger}; }; // map floating point to double. (truncates long double, but then PVA doesn't >8 byte primatives anyway support anyway) @@ -57,6 +58,10 @@ template struct StorageMap{}>::type> { typedef double store_t; static constexpr StoreType code{StoreType::Real}; }; +template<> +struct StorageMap +{ typedef bool store_t; static constexpr StoreType code{StoreType::Bool}; }; + template<> struct StorageMap { typedef std::string store_t; static constexpr StoreType code{StoreType::String}; };