diff --git a/src/data.cpp b/src/data.cpp index 4486fdf..089fc1f 100644 --- a/src/data.cpp +++ b/src/data.cpp @@ -18,10 +18,6 @@ NoField::NoField() NoField::~NoField() {} -NoConvert::NoConvert() - :std::runtime_error ("No conversion defined") -{} - NoConvert::~NoConvert() {} LookupError::LookupError(const std::string& msg) @@ -457,8 +453,6 @@ void Value::copyOut(void *ptr, StoreType type) const src.copyOut(ptr, type); return; - } else { - throw NoConvert(); } break; @@ -467,7 +461,7 @@ void Value::copyOut(void *ptr, StoreType type) const break; } - throw NoConvert(); + throw NoConvert(SB()<<"Can't extract "<type()<<" as "<code) { case StoreType::Real: { - if(!copyInScalar(store->as(), ptr, type)) throw NoConvert(); + if(!copyInScalar(store->as(), ptr, type)) throw NoConvert(SB()<<"Unable to assign "<code<<" with "<code==TypeCode::Float32) store->as() = float(store->as()); break; } case StoreType::Integer: { - if(!copyInScalar(store->as(), ptr, type)) throw NoConvert(); + if(!copyInScalar(store->as(), ptr, type)) throw NoConvert(SB()<<"Unable to assign "<code<<" with "<as(); switch(desc->code.code) { @@ -534,7 +528,7 @@ void Value::copyIn(const void *ptr, StoreType type) break; } case StoreType::UInteger: { - if(!copyInScalar(store->as(), ptr, type)) throw NoConvert(); + if(!copyInScalar(store->as(), ptr, type)) throw NoConvert(SB()<<"Unable to assign "<code<<" with "<as(); switch(desc->code.code) { @@ -559,7 +553,7 @@ void Value::copyIn(const void *ptr, StoreType type) else if("false"==*reinterpret_cast(ptr)) { dest = false; break; } // fall through default: - throw NoConvert(); + throw NoConvert(SB()<<"Unable to assign "<code<<" with "<(ptr); break; case StoreType::Bool: dest = (*reinterpret_cast(ptr)) ? "true" : "false"; break; default: - throw NoConvert(); + throw NoConvert(SB()<<"Unable to assign "<code<<" with "<members.data()) { - throw NoConvert(); + throw NoConvert(SB()<<"Unable to assign "<code<<" with "<code<<" with "<code<<" with "<code<<" with "<(ptr); @@ -663,7 +657,7 @@ void Value::copyIn(const void *ptr, StoreType type) return; } } - throw NoConvert(); + throw NoConvert(SB()<<"Unable to assign "<code<<" with "< }; +PVXS_API +std::ostream& operator<<(std::ostream& strm, StoreType c); + constexpr struct unselect_t {} unselect; namespace impl { @@ -450,7 +453,7 @@ struct PVXS_API NoField : public std::runtime_error //! Thrown when a Value can not be converted to the requested type struct PVXS_API NoConvert : public std::runtime_error { - explicit NoConvert(); + NoConvert(const std::string& msg) : std::runtime_error(msg) {} virtual ~NoConvert(); }; @@ -521,7 +524,7 @@ public: //! Use to allocate members for an array of Struct and array of Union Value allocMember(); - //! Does this Value actual reference some underlying storage + //! Does this Value actually reference some underlying storage inline bool valid() const { return desc; } inline explicit operator bool() const { return desc; } @@ -581,6 +584,9 @@ public: * - std::string * - Value * - shared_array + * + * @throws NoField !this->valid() + * @throws NoConvert if the field value can not be coerced to type T */ template inline T as() const { diff --git a/src/type.cpp b/src/type.cpp index ba08f00..6574d2b 100644 --- a/src/type.cpp +++ b/src/type.cpp @@ -12,6 +12,24 @@ namespace pvxs { +std::ostream& operator<<(std::ostream& strm, StoreType c) +{ + const char* name = "<\?\?\?>"; + switch(c) { +#define CASE(CODE) case StoreType::CODE: name = #CODE; break + CASE(Null); + CASE(Bool); + CASE(Real); + CASE(Integer); + CASE(UInteger); + CASE(String); + CASE(Compound); + CASE(Array); +#undef CASE + } + return strm< double parseTo(const std::string& s) { size_t idx=0, L=s.size(); - double ret = std::stod(s, &idx); + double ret; + try { + ret = std::stod(s, &idx); + }catch(std::invalid_argument& e) { + throw NoConvert(SB()<<"Invalid input : \""< uint64_t parseTo(const std::string& s) { size_t idx=0, L=s.size(); - unsigned long long ret = std::stoull(s, &idx, 0); + unsigned long long ret; + try { + ret = std::stoull(s, &idx, 0); + }catch(std::invalid_argument& e) { + throw NoConvert(SB()<<"Invalid input : \""< int64_t parseTo(const std::string& s) { size_t idx=0, L=s.size(); - long long ret = std::stoll(s, &idx, 0); + long long ret; + try { + ret = std::stoll(s, &idx, 0); + }catch(std::invalid_argument& e) { + throw NoConvert(SB()<<"Invalid input : \""<"].valid()); - testThrows([&val](){ + testThrows([&val](){ val["->u16"] = "hello"; });