/** * Copyright - See the COPYRIGHT that is included with this distribution. * pvxs is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. */ #include #include #include #include #include "utilpvt.h" namespace pvxs { std::ostream& operator<<(std::ostream& strm, ArrayType code) { switch(code) { #define CASE(CODE) case ArrayType::CODE : strm<<#CODE; break CASE(Null); CASE(Bool); CASE(UInt8); CASE(UInt16); CASE(UInt32); CASE(UInt64); CASE(Int8); CASE(Int16); CASE(Int32); CASE(Int64); CASE(Float32); CASE(Float64); CASE(Value); #undef CASE default: strm<<"<\?\?\?>"; } return strm; } size_t elementSize(ArrayType type) { switch(type) { #define CASE(CODE, Type) case ArrayType::CODE: return sizeof(Type) CASE(Bool, bool); CASE(UInt8, uint8_t); CASE(UInt16, uint16_t); CASE(UInt32, uint32_t); CASE(UInt64, uint64_t); CASE(Int8, int8_t); CASE(Int16, int16_t); CASE(Int32, int32_t); CASE(Int64, int64_t); CASE(Float32, float); CASE(Float64, double); CASE(String, std::string); CASE(Value, Value); #undef CASE case ArrayType::Null: break; } throw std::logic_error("Invalid ArrayType"); } shared_array allocArray(ArrayType type, size_t count) { switch(type) { #define CASE(CODE, TYPE) case ArrayType::CODE: return shared_array(count).castTo() CASE(Bool, bool); CASE(UInt8, uint8_t); CASE(UInt16, uint16_t); CASE(UInt32, uint32_t); CASE(UInt64, uint64_t); CASE(Int8, int8_t); CASE(Int16, int16_t); CASE(Int32, int32_t); CASE(Int64, int64_t); CASE(Float32, float); CASE(Float64, double); CASE(String, std::string); CASE(Value, Value); #undef CASE case ArrayType::Null: break; } throw std::logic_error("Invalid ArrayType"); } namespace detail { namespace { template struct Print { static inline void as(std::ostream& strm,const E& val) { strm< struct Print { static inline void as(std::ostream& strm,int8_t val) { strm< struct Print { static inline void as(std::ostream& strm,uint8_t val) { strm< struct Print { static inline void as(std::ostream& strm,const std::string& val) { strm<<"\""< void showArr(std::ostream& strm, const void* raw, size_t count, size_t limit) { auto base = reinterpret_cast(raw); if(limit==0) limit=size_t(-1); strm<<"{"<limit) { strm<<"..."; break; } Print::as(strm, base[i]); } strm<<']'; } } // namespace std::ostream& operator<<(std::ostream& strm, const Limiter& lim) { switch(lim._type) { #define CASE(CODE, Type) case ArrayType::CODE: showArr(strm, lim._base, lim._count, lim._limit); break CASE(Bool, bool); CASE(UInt8, uint8_t); CASE(UInt16, uint16_t); CASE(UInt32, uint32_t); CASE(UInt64, uint64_t); CASE(Int8, int8_t); CASE(Int16, int16_t); CASE(Int32, int32_t); CASE(Int64, int64_t); CASE(Float32, float); CASE(Float64, double); CASE(String, std::string); #undef CASE case ArrayType::Null: strm<<"{\?}[]"; break; default: strm<<"[\?\?\?]"; } return strm; } void _throw_bad_cast(ArrayType from, ArrayType to) { throw std::logic_error(SB()<<"Unable to cast array from "< void convertCast(const void *sbase, void *dbase, size_t count) { auto S = static_cast(sbase); auto D = static_cast(dbase); for(auto i : range(count)) D[i] = Dest(S[i]); } void printValue(std::string& dest, const bool& src) { dest = src ? "true" : "false"; } template typename std::enable_if::value>::type printValue(std::string& dest, const Src& src) { std::ostringstream strm; strm< void convertToStr(const void *sbase, void *dbase, size_t count) { auto S = static_cast(sbase); auto D = static_cast(dbase); for(auto i : range(count)) printValue(D[i], S[i]); } void parseValue(bool& dest, const std::string& src) { if(src=="true") dest = true; else if(src=="false") dest = false; else throw std::runtime_error(SB()<<"Expected \"true\" or \"false\", not \""< typename std::enable_if::value && std::is_signed::value>::type parseValue(Dest& dest, const std::string& src) { dest = Dest(parseTo(src)); } template typename std::enable_if::value && !std::is_signed::value && !std::is_same::value>::type parseValue(Dest& dest, const std::string& src) { dest = Dest(parseTo(src)); } template typename std::enable_if::value>::type parseValue(Dest& dest, const std::string& src) { dest = Dest(parseTo(src)); } template void convertFromStr(const void *sbase, void *dbase, size_t count) { auto S = static_cast(sbase); auto D = static_cast(dbase); for(auto i : range(count)) parseValue(D[i], S[i]); } } // namespace void convertArr(ArrayType dtype, void *dbase, ArrayType stype, const void *sbase, size_t count) { switch (stype) { case ArrayType::Bool: switch(dtype) { case ArrayType::Bool: memcpy(dbase, sbase, count*sizeof(bool)); return; case ArrayType::Int8: case ArrayType::UInt8: convertCast(sbase, dbase, count); return; case ArrayType::Int16: case ArrayType::UInt16: convertCast(sbase, dbase, count); return; case ArrayType::Int32: case ArrayType::UInt32: convertCast(sbase, dbase, count); return; case ArrayType::Int64: case ArrayType::UInt64: convertCast(sbase, dbase, count); return; case ArrayType::Float32:convertCast(sbase, dbase, count); return; case ArrayType::Float64:convertCast(sbase, dbase, count); return; case ArrayType::String: convertToStr(sbase, dbase, count); return; case ArrayType::Value: case ArrayType::Null: break; // no convert } break; case ArrayType::Int8: switch(dtype) { case ArrayType::Bool: convertCast(sbase, dbase, count); return; case ArrayType::Int8: case ArrayType::UInt8: memcpy(dbase, sbase, count*sizeof(int8_t)); return; // cast sint -> *int always sign extends case ArrayType::Int16: case ArrayType::UInt16: convertCast(sbase, dbase, count); return; case ArrayType::Int32: case ArrayType::UInt32: convertCast(sbase, dbase, count); return; case ArrayType::Int64: case ArrayType::UInt64: convertCast(sbase, dbase, count); return; case ArrayType::Float32:convertCast(sbase, dbase, count); return; case ArrayType::Float64:convertCast(sbase, dbase, count); return; case ArrayType::String: convertToStr(sbase, dbase, count); return; case ArrayType::Value: case ArrayType::Null: break; // no convert } break; case ArrayType::Int16: switch(dtype) { case ArrayType::Bool: convertCast(sbase, dbase, count); return; case ArrayType::Int8: case ArrayType::UInt8: convertCast(sbase, dbase, count); return; case ArrayType::Int16: case ArrayType::UInt16: memcpy(dbase, sbase, count*sizeof(int16_t)); return; case ArrayType::Int32: case ArrayType::UInt32: convertCast(sbase, dbase, count); return; case ArrayType::Int64: case ArrayType::UInt64: convertCast(sbase, dbase, count); return; case ArrayType::Float32:convertCast(sbase, dbase, count); return; case ArrayType::Float64:convertCast(sbase, dbase, count); return; case ArrayType::String: convertToStr(sbase, dbase, count); return; case ArrayType::Value: case ArrayType::Null: break; // no convert } break; case ArrayType::Int32: switch(dtype) { case ArrayType::Bool: convertCast(sbase, dbase, count); return; case ArrayType::Int8: case ArrayType::UInt8: convertCast(sbase, dbase, count); return; case ArrayType::Int16: case ArrayType::UInt16: convertCast(sbase, dbase, count); return; case ArrayType::Int32: case ArrayType::UInt32: memcpy(dbase, sbase, count*sizeof(int32_t)); return; case ArrayType::Int64: case ArrayType::UInt64: convertCast(sbase, dbase, count); return; case ArrayType::Float32:convertCast(sbase, dbase, count); return; case ArrayType::Float64:convertCast(sbase, dbase, count); return; case ArrayType::String: convertToStr(sbase, dbase, count); return; case ArrayType::Value: case ArrayType::Null: break; // no convert } break; case ArrayType::Int64: switch(dtype) { case ArrayType::Bool: convertCast(sbase, dbase, count); return; case ArrayType::Int8: case ArrayType::UInt8: convertCast(sbase, dbase, count); return; case ArrayType::Int16: case ArrayType::UInt16: convertCast(sbase, dbase, count); return; case ArrayType::Int32: case ArrayType::UInt32: convertCast(sbase, dbase, count); return; case ArrayType::Int64: case ArrayType::UInt64: memcpy(dbase, sbase, count*sizeof(int64_t)); return; case ArrayType::Float32:convertCast(sbase, dbase, count); return; case ArrayType::Float64:convertCast(sbase, dbase, count); return; case ArrayType::String: convertToStr(sbase, dbase, count); return; case ArrayType::Value: case ArrayType::Null: break; // no convert } break; case ArrayType::UInt8: switch(dtype) { case ArrayType::Bool: convertCast(sbase, dbase, count); return; case ArrayType::Int8: case ArrayType::UInt8: memcpy(dbase, sbase, count*sizeof(uint8_t)); return; //case uint -> *int never sign extends case ArrayType::Int16: case ArrayType::UInt16: convertCast(sbase, dbase, count); return; case ArrayType::Int32: case ArrayType::UInt32: convertCast(sbase, dbase, count); return; case ArrayType::Int64: case ArrayType::UInt64: convertCast(sbase, dbase, count); return; case ArrayType::Float32:convertCast(sbase, dbase, count); return; case ArrayType::Float64:convertCast(sbase, dbase, count); return; case ArrayType::String: convertToStr(sbase, dbase, count); return; case ArrayType::Value: case ArrayType::Null: break; // no convert } break; case ArrayType::UInt16: switch(dtype) { case ArrayType::Bool: convertCast(sbase, dbase, count); return; case ArrayType::Int8: case ArrayType::UInt8: convertCast(sbase, dbase, count); return; case ArrayType::Int16: case ArrayType::UInt16: memcpy(dbase, sbase, count*sizeof(uint16_t)); return; case ArrayType::Int32: case ArrayType::UInt32: convertCast(sbase, dbase, count); return; case ArrayType::Int64: case ArrayType::UInt64: convertCast(sbase, dbase, count); return; case ArrayType::Float32:convertCast(sbase, dbase, count); return; case ArrayType::Float64:convertCast(sbase, dbase, count); return; case ArrayType::String: convertToStr(sbase, dbase, count); return; case ArrayType::Value: case ArrayType::Null: break; // no convert } break; case ArrayType::UInt32: switch(dtype) { case ArrayType::Bool: convertCast(sbase, dbase, count); return; case ArrayType::Int8: case ArrayType::UInt8: convertCast(sbase, dbase, count); return; case ArrayType::Int16: case ArrayType::UInt16: convertCast(sbase, dbase, count); return; case ArrayType::Int32: case ArrayType::UInt32: memcpy(dbase, sbase, count*sizeof(uint32_t)); return; case ArrayType::Int64: case ArrayType::UInt64: convertCast(sbase, dbase, count); return; case ArrayType::Float32:convertCast(sbase, dbase, count); return; case ArrayType::Float64:convertCast(sbase, dbase, count); return; case ArrayType::String: convertToStr(sbase, dbase, count); return; case ArrayType::Value: case ArrayType::Null: break; // no convert } break; case ArrayType::UInt64: switch(dtype) { case ArrayType::Bool: convertCast(sbase, dbase, count); return; case ArrayType::Int8: case ArrayType::UInt8: convertCast(sbase, dbase, count); return; case ArrayType::Int16: case ArrayType::UInt16: convertCast(sbase, dbase, count); return; case ArrayType::Int32: case ArrayType::UInt32: convertCast(sbase, dbase, count); return; case ArrayType::Int64: case ArrayType::UInt64: memcpy(dbase, sbase, count*sizeof(uint64_t)); return; case ArrayType::Float32:convertCast(sbase, dbase, count); return; case ArrayType::Float64:convertCast(sbase, dbase, count); return; case ArrayType::String: convertToStr(sbase, dbase, count); return; case ArrayType::Value: case ArrayType::Null: break; // no convert } break; case ArrayType::Float32: switch(dtype) { case ArrayType::Bool: convertCast(sbase, dbase, count); return; case ArrayType::Int8: case ArrayType::UInt8: convertCast(sbase, dbase, count); return; case ArrayType::Int16: case ArrayType::UInt16: convertCast(sbase, dbase, count); return; case ArrayType::Int32: case ArrayType::UInt32: convertCast(sbase, dbase, count); return; case ArrayType::Int64: case ArrayType::UInt64: convertCast(sbase, dbase, count); return; case ArrayType::Float32:memcpy(dbase, sbase, count*sizeof(float)); return; case ArrayType::Float64:convertCast(sbase, dbase, count); return; case ArrayType::String: convertToStr(sbase, dbase, count); return; case ArrayType::Value: case ArrayType::Null: break; // no convert } break; case ArrayType::Float64: switch(dtype) { case ArrayType::Bool: convertCast(sbase, dbase, count); return; case ArrayType::Int8: case ArrayType::UInt8: convertCast(sbase, dbase, count); return; case ArrayType::Int16: case ArrayType::UInt16: convertCast(sbase, dbase, count); return; case ArrayType::Int32: case ArrayType::UInt32: convertCast(sbase, dbase, count); return; case ArrayType::Int64: case ArrayType::UInt64: convertCast(sbase, dbase, count); return; case ArrayType::Float32:memcpy(dbase, sbase, count*sizeof(double)); return; case ArrayType::Float64:convertCast(sbase, dbase, count); return; case ArrayType::String: convertToStr(sbase, dbase, count); return; case ArrayType::Value: case ArrayType::Null: break; // no convert } break; case ArrayType::String: switch(dtype) { case ArrayType::Bool: convertFromStr(sbase, dbase, count); return; case ArrayType::Int8: convertFromStr(sbase, dbase, count); return; case ArrayType::UInt8: convertFromStr(sbase, dbase, count); return; case ArrayType::Int16: convertFromStr(sbase, dbase, count); return; case ArrayType::UInt16: convertFromStr(sbase, dbase, count); return; case ArrayType::Int32: convertFromStr(sbase, dbase, count); return; case ArrayType::UInt32: convertFromStr(sbase, dbase, count); return; case ArrayType::Int64: convertFromStr(sbase, dbase, count); return; case ArrayType::UInt64: convertFromStr(sbase, dbase, count); return; case ArrayType::Float32:convertFromStr(sbase, dbase, count); return; case ArrayType::Float64:convertFromStr(sbase, dbase, count); return; break; case ArrayType::String: convertCast(sbase, dbase, count); return; case ArrayType::Value: case ArrayType::Null: break; // no convert } break; case ArrayType::Value: case ArrayType::Null: break; } throw NoConvert(); } shared_array copyAs(ArrayType dtype, ArrayType stype, const void *sbase, size_t count) { shared_array ret; switch(dtype) { #define CASE(CODE, Type) case ArrayType::CODE: ret = shared_array(count).castTo(); break CASE(Bool, bool); CASE(UInt8, uint8_t); CASE(UInt16, uint16_t); CASE(UInt32, uint32_t); CASE(UInt64, uint64_t); CASE(Int8, int8_t); CASE(Int16, int16_t); CASE(Int32, int32_t); CASE(Int64, int64_t); CASE(Float32, float); CASE(Float64, double); CASE(String, std::string); CASE(Value, Value); #undef CASE case ArrayType::Null: break; } if(stype!=ArrayType::Null) convertArr(dtype, ret.data(), stype, sbase, count); return ret; } } // namespace detail } // namespace pvxs