/* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ #include "qpid/types/Variant.h" #include "qpid/log/Statement.h" #include #include #include #include #include #include namespace qpid { namespace types { namespace { const std::string EMPTY; const std::string PREFIX("invalid conversion: "); } InvalidConversion::InvalidConversion(const std::string& msg) : Exception(PREFIX + msg) {} class VariantImpl { public: VariantImpl(); VariantImpl(bool); VariantImpl(uint8_t); VariantImpl(uint16_t); VariantImpl(uint32_t); VariantImpl(uint64_t); VariantImpl(int8_t); VariantImpl(int16_t); VariantImpl(int32_t); VariantImpl(int64_t); VariantImpl(float); VariantImpl(double); VariantImpl(const std::string&, const std::string& encoding=std::string()); VariantImpl(const Variant::Map&); VariantImpl(const Variant::List&); VariantImpl(const Uuid&); ~VariantImpl(); VariantType getType() const; bool asBool() const; uint8_t asUint8() const; uint16_t asUint16() const; uint32_t asUint32() const; uint64_t asUint64() const; int8_t asInt8() const; int16_t asInt16() const; int32_t asInt32() const; int64_t asInt64() const; float asFloat() const; double asDouble() const; std::string asString() const; Uuid asUuid() const; const Variant::Map& asMap() const; Variant::Map& asMap(); const Variant::List& asList() const; Variant::List& asList(); const std::string& getString() const; std::string& getString(); void setEncoding(const std::string&); const std::string& getEncoding() const; bool isEqualTo(VariantImpl&) const; bool isEquivalentTo(VariantImpl&) const; static VariantImpl* create(const Variant&); private: const VariantType type; union { bool b; uint8_t ui8; uint16_t ui16; uint32_t ui32; uint64_t ui64; int8_t i8; int16_t i16; int32_t i32; int64_t i64; float f; double d; void* v;//variable width data } value; std::string encoding;//optional encoding for variable length data template T convertFromString() const { std::string* s = reinterpret_cast(value.v); if (std::numeric_limits::is_signed || s->find('-') != 0) { //lexical_cast won't fail if string is a negative number and T is unsigned try { return boost::lexical_cast(*s); } catch(const boost::bad_lexical_cast&) { //don't return, throw exception below } } else { //T is unsigned and number starts with '-' try { //handle special case of negative zero if (boost::lexical_cast(*s) == 0) return 0; //else its a non-zero negative number so throw exception at end of function } catch(const boost::bad_lexical_cast&) { //wasn't a valid int, therefore not a valid uint } } throw InvalidConversion(QPID_MSG("Cannot convert " << *s)); } }; VariantImpl::VariantImpl() : type(VAR_VOID) { value.i64 = 0; } VariantImpl::VariantImpl(bool b) : type(VAR_BOOL) { value.b = b; } VariantImpl::VariantImpl(uint8_t i) : type(VAR_UINT8) { value.ui8 = i; } VariantImpl::VariantImpl(uint16_t i) : type(VAR_UINT16) { value.ui16 = i; } VariantImpl::VariantImpl(uint32_t i) : type(VAR_UINT32) { value.ui32 = i; } VariantImpl::VariantImpl(uint64_t i) : type(VAR_UINT64) { value.ui64 = i; } VariantImpl::VariantImpl(int8_t i) : type(VAR_INT8) { value.i8 = i; } VariantImpl::VariantImpl(int16_t i) : type(VAR_INT16) { value.i16 = i; } VariantImpl::VariantImpl(int32_t i) : type(VAR_INT32) { value.i32 = i; } VariantImpl::VariantImpl(int64_t i) : type(VAR_INT64) { value.i64 = i; } VariantImpl::VariantImpl(float f) : type(VAR_FLOAT) { value.f = f; } VariantImpl::VariantImpl(double d) : type(VAR_DOUBLE) { value.d = d; } VariantImpl::VariantImpl(const std::string& s, const std::string& e) : type(VAR_STRING), encoding(e) { value.v = new std::string(s); } VariantImpl::VariantImpl(const Variant::Map& m) : type(VAR_MAP) { value.v = new Variant::Map(m); } VariantImpl::VariantImpl(const Variant::List& l) : type(VAR_LIST) { value.v = new Variant::List(l); } VariantImpl::VariantImpl(const Uuid& u) : type(VAR_UUID) { value.v = new Uuid(u); } VariantImpl::~VariantImpl() { switch (type) { case VAR_STRING: delete reinterpret_cast(value.v); break; case VAR_MAP: delete reinterpret_cast(value.v); break; case VAR_LIST: delete reinterpret_cast(value.v); break; case VAR_UUID: delete reinterpret_cast(value.v); break; default: break; } } VariantType VariantImpl::getType() const { return type; } namespace { bool same_char(char a, char b) { return toupper(a) == toupper(b); } bool caseInsensitiveMatch(const std::string& a, const std::string& b) { return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin(), &same_char); } const std::string TRUE("True"); const std::string FALSE("False"); bool toBool(const std::string& s) { if (caseInsensitiveMatch(s, TRUE)) return true; if (caseInsensitiveMatch(s, FALSE)) return false; try { return boost::lexical_cast(s); } catch(const boost::bad_lexical_cast&) {} throw InvalidConversion(QPID_MSG("Cannot convert " << s << " to bool")); } template std::string toString(const T& t) { std::stringstream out; out << t; return out.str(); } template bool equal(const T& a, const T& b) { return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin()); } } bool VariantImpl::asBool() const { switch(type) { case VAR_VOID: return false; case VAR_BOOL: return value.b; case VAR_UINT8: return value.ui8; case VAR_UINT16: return value.ui16; case VAR_UINT32: return value.ui32; case VAR_UINT64: return value.ui64; case VAR_INT8: return value.i8; case VAR_INT16: return value.i16; case VAR_INT32: return value.i32; case VAR_INT64: return value.i64; case VAR_STRING: return toBool(*reinterpret_cast(value.v)); default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_BOOL))); } } uint8_t VariantImpl::asUint8() const { switch(type) { case VAR_UINT8: return value.ui8; case VAR_UINT16: if (value.ui16 <= 0x00ff) return uint8_t(value.ui16); break; case VAR_UINT32: if (value.ui32 <= 0x000000ff) return uint8_t(value.ui32); break; case VAR_UINT64: if (value.ui64 <= 0x00000000000000ff) return uint8_t(value.ui64); break; case VAR_INT8: if (value.i8 >= 0) return uint8_t(value.i8); break; case VAR_INT16: if (value.i16 >= 0 && value.i16 <= 0x00ff) return uint8_t(value.i16); break; case VAR_INT32: if (value.i32 >= 0 && value.i32 <= 0x000000ff) return uint8_t(value.i32); break; case VAR_INT64: if (value.i64 >= 0 && value.i64 <= 0x00000000000000ff) return uint8_t(value.i64); break; case VAR_STRING: return convertFromString(); default: break; } throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_UINT8))); } uint16_t VariantImpl::asUint16() const { switch(type) { case VAR_UINT8: return value.ui8; case VAR_UINT16: return value.ui16; case VAR_UINT32: if (value.ui32 <= 0x0000ffff) return uint16_t(value.ui32); break; case VAR_UINT64: if (value.ui64 <= 0x000000000000ffff) return uint16_t(value.ui64); break; case VAR_INT8: if (value.i8 >= 0) return uint16_t(value.i8); break; case VAR_INT16: if (value.i16 >= 0) return uint16_t(value.i16); break; case VAR_INT32: if (value.i32 >= 0 && value.i32 <= 0x0000ffff) return uint16_t(value.i32); break; case VAR_INT64: if (value.i64 >= 0 && value.i64 <= 0x000000000000ffff) return uint16_t(value.i64); break; case VAR_STRING: return convertFromString(); default: break; } throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_UINT16))); } uint32_t VariantImpl::asUint32() const { switch(type) { case VAR_UINT8: return value.ui8; case VAR_UINT16: return value.ui16; case VAR_UINT32: return value.ui32; case VAR_UINT64: if (value.ui64 <= 0x00000000ffffffff) return uint32_t(value.ui64); break; case VAR_INT8: if (value.i8 >= 0) return uint32_t(value.i8); break; case VAR_INT16: if (value.i16 >= 0) return uint32_t(value.i16); break; case VAR_INT32: if (value.i32 >= 0) return uint32_t(value.i32); break; case VAR_INT64: if (value.i64 >= 0 && value.i64 <= 0x00000000ffffffff) return uint32_t(value.i64); break; case VAR_STRING: return convertFromString(); default: break; } throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_UINT32))); } uint64_t VariantImpl::asUint64() const { switch(type) { case VAR_UINT8: return value.ui8; case VAR_UINT16: return value.ui16; case VAR_UINT32: return value.ui32; case VAR_UINT64: return value.ui64; case VAR_INT8: if (value.i8 >= 0) return uint64_t(value.i8); break; case VAR_INT16: if (value.i16 >= 0) return uint64_t(value.i16); break; case VAR_INT32: if (value.i32 >= 0) return uint64_t(value.i32); break; case VAR_INT64: if (value.i64 >= 0) return uint64_t(value.i64); break; case VAR_STRING: return convertFromString(); default: break; } throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_UINT64))); } int8_t VariantImpl::asInt8() const { switch(type) { case VAR_INT8: return value.i8; case VAR_INT16: if ((value.i16 >= std::numeric_limits::min()) && (value.i16 <= std::numeric_limits::max())) return int8_t(value.i16); break; case VAR_INT32: if ((value.i32 >= std::numeric_limits::min()) && (value.i32 <= std::numeric_limits::max())) return int8_t(value.i32); break; case VAR_INT64: if ((value.i64 >= std::numeric_limits::min()) && (value.i64 <= std::numeric_limits::max())) return int8_t(value.i64); break; case VAR_UINT8: if (value.ui8 <= std::numeric_limits::max()) return int8_t(value.ui8); break; case VAR_UINT16: if (value.ui16 <= std::numeric_limits::max()) return int8_t(value.ui16); break; case VAR_UINT32: if (value.ui32 <= (uint32_t) std::numeric_limits::max()) return int8_t(value.ui32); break; case VAR_UINT64: if (value.ui64 <= (uint64_t) std::numeric_limits::max()) return int8_t(value.ui64); break; case VAR_STRING: return convertFromString(); default: break; } throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_INT8))); } int16_t VariantImpl::asInt16() const { switch(type) { case VAR_INT8: return value.i8; case VAR_INT16: return value.i16; case VAR_INT32: if ((value.i32 >= std::numeric_limits::min()) && (value.i32 <= std::numeric_limits::max())) return int16_t(value.i32); break; case VAR_INT64: if ((value.i64 >= std::numeric_limits::min()) && (value.i64 <= std::numeric_limits::max())) return int16_t(value.i64); break; case VAR_UINT8: return int16_t(value.ui8); case VAR_UINT16: if (value.ui16 <= std::numeric_limits::max()) return int16_t(value.ui16); break; case VAR_UINT32: if (value.ui32 <= (uint32_t) std::numeric_limits::max()) return int16_t(value.ui32); break; case VAR_UINT64: if (value.ui64 <= (uint64_t) std::numeric_limits::max()) return int16_t(value.ui64); break; case VAR_STRING: return convertFromString(); default: break; } throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_INT16))); } int32_t VariantImpl::asInt32() const { switch(type) { case VAR_INT8: return value.i8; case VAR_INT16: return value.i16; case VAR_INT32: return value.i32; case VAR_INT64: if ((value.i64 >= std::numeric_limits::min()) && (value.i64 <= std::numeric_limits::max())) return int32_t(value.i64); break; case VAR_UINT8: return int32_t(value.ui8); case VAR_UINT16: return int32_t(value.ui16); case VAR_UINT32: if (value.ui32 <= (uint32_t) std::numeric_limits::max()) return int32_t(value.ui32); break; case VAR_UINT64: if (value.ui64 <= (uint64_t) std::numeric_limits::max()) return int32_t(value.ui64); break; case VAR_STRING: return convertFromString(); default: break; } throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_INT32))); } int64_t VariantImpl::asInt64() const { switch(type) { case VAR_INT8: return value.i8; case VAR_INT16: return value.i16; case VAR_INT32: return value.i32; case VAR_INT64: return value.i64; case VAR_UINT8: return int64_t(value.ui8); case VAR_UINT16: return int64_t(value.ui16); case VAR_UINT32: return int64_t(value.ui32); case VAR_UINT64: if (value.ui64 <= (uint64_t) std::numeric_limits::max()) return int64_t(value.ui64); break; case VAR_STRING: return convertFromString(); default: break; } throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_INT64))); } float VariantImpl::asFloat() const { switch(type) { case VAR_FLOAT: return value.f; case VAR_STRING: return convertFromString(); default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_FLOAT))); } } double VariantImpl::asDouble() const { switch(type) { case VAR_FLOAT: return value.f; case VAR_DOUBLE: return value.d; case VAR_STRING: return convertFromString(); default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_DOUBLE))); } } std::string VariantImpl::asString() const { switch(type) { case VAR_VOID: return EMPTY; case VAR_BOOL: return value.b ? TRUE : FALSE; case VAR_UINT8: return boost::lexical_cast((int) value.ui8); case VAR_UINT16: return boost::lexical_cast(value.ui16); case VAR_UINT32: return boost::lexical_cast(value.ui32); case VAR_UINT64: return boost::lexical_cast(value.ui64); case VAR_INT8: return boost::lexical_cast((int) value.i8); case VAR_INT16: return boost::lexical_cast(value.i16); case VAR_INT32: return boost::lexical_cast(value.i32); case VAR_INT64: return boost::lexical_cast(value.i64); case VAR_DOUBLE: return boost::lexical_cast(value.d); case VAR_FLOAT: return boost::lexical_cast(value.f); case VAR_STRING: return *reinterpret_cast(value.v); case VAR_UUID: return reinterpret_cast(value.v)->str(); case VAR_LIST: return toString(asList()); case VAR_MAP: return toString(asMap()); default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_STRING))); } } Uuid VariantImpl::asUuid() const { switch(type) { case VAR_UUID: return *reinterpret_cast(value.v); default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_UUID))); } } bool VariantImpl::isEqualTo(VariantImpl& other) const { if (type == other.type) { switch(type) { case VAR_VOID: return true; case VAR_BOOL: return value.b == other.value.b; case VAR_UINT8: return value.ui8 == other.value.ui8; case VAR_UINT16: return value.ui16 == other.value.ui16; case VAR_UINT32: return value.ui32 == other.value.ui32; case VAR_UINT64: return value.ui64 == other.value.ui64; case VAR_INT8: return value.i8 == other.value.i8; case VAR_INT16: return value.i16 == other.value.i16; case VAR_INT32: return value.i32 == other.value.i32; case VAR_INT64: return value.i64 == other.value.i64; case VAR_DOUBLE: return value.d == other.value.d; case VAR_FLOAT: return value.f == other.value.f; case VAR_STRING: return *reinterpret_cast(value.v) == *reinterpret_cast(other.value.v); case VAR_UUID: return *reinterpret_cast(value.v) == *reinterpret_cast(other.value.v); case VAR_LIST: return equal(asList(), other.asList()); case VAR_MAP: return equal(asMap(), other.asMap()); } } return false; } const Variant::Map& VariantImpl::asMap() const { switch(type) { case VAR_MAP: return *reinterpret_cast(value.v); default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_MAP))); } } Variant::Map& VariantImpl::asMap() { switch(type) { case VAR_MAP: return *reinterpret_cast(value.v); default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_MAP))); } } const Variant::List& VariantImpl::asList() const { switch(type) { case VAR_LIST: return *reinterpret_cast(value.v); default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_LIST))); } } Variant::List& VariantImpl::asList() { switch(type) { case VAR_LIST: return *reinterpret_cast(value.v); default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_LIST))); } } std::string& VariantImpl::getString() { switch(type) { case VAR_STRING: return *reinterpret_cast(value.v); default: throw InvalidConversion(QPID_MSG("Variant is not a string; use asString() if conversion is required.")); } } const std::string& VariantImpl::getString() const { switch(type) { case VAR_STRING: return *reinterpret_cast(value.v); default: throw InvalidConversion(QPID_MSG("Variant is not a string; use asString() if conversion is required.")); } } void VariantImpl::setEncoding(const std::string& s) { encoding = s; } const std::string& VariantImpl::getEncoding() const { return encoding; } std::string getTypeName(VariantType type) { switch (type) { case VAR_VOID: return "void"; case VAR_BOOL: return "bool"; case VAR_UINT8: return "uint8"; case VAR_UINT16: return "uint16"; case VAR_UINT32: return "uint32"; case VAR_UINT64: return "uint64"; case VAR_INT8: return "int8"; case VAR_INT16: return "int16"; case VAR_INT32: return "int32"; case VAR_INT64: return "int64"; case VAR_FLOAT: return "float"; case VAR_DOUBLE: return "double"; case VAR_STRING: return "string"; case VAR_MAP: return "map"; case VAR_LIST: return "list"; case VAR_UUID: return "uuid"; } return "";//should never happen } VariantImpl* VariantImpl::create(const Variant& v) { switch (v.getType()) { case VAR_BOOL: return new VariantImpl(v.asBool()); case VAR_UINT8: return new VariantImpl(v.asUint8()); case VAR_UINT16: return new VariantImpl(v.asUint16()); case VAR_UINT32: return new VariantImpl(v.asUint32()); case VAR_UINT64: return new VariantImpl(v.asUint64()); case VAR_INT8: return new VariantImpl(v.asInt8()); case VAR_INT16: return new VariantImpl(v.asInt16()); case VAR_INT32: return new VariantImpl(v.asInt32()); case VAR_INT64: return new VariantImpl(v.asInt64()); case VAR_FLOAT: return new VariantImpl(v.asFloat()); case VAR_DOUBLE: return new VariantImpl(v.asDouble()); case VAR_STRING: return new VariantImpl(v.asString(), v.getEncoding()); case VAR_MAP: return new VariantImpl(v.asMap()); case VAR_LIST: return new VariantImpl(v.asList()); case VAR_UUID: return new VariantImpl(v.asUuid()); default: return new VariantImpl(); } } Variant::Variant() : impl(0) {} Variant::Variant(bool b) : impl(new VariantImpl(b)) {} Variant::Variant(uint8_t i) : impl(new VariantImpl(i)) {} Variant::Variant(uint16_t i) : impl(new VariantImpl(i)) {} Variant::Variant(uint32_t i) : impl(new VariantImpl(i)) {} Variant::Variant(uint64_t i) : impl(new VariantImpl(i)) {} Variant::Variant(int8_t i) : impl(new VariantImpl(i)) {} Variant::Variant(int16_t i) : impl(new VariantImpl(i)) {} Variant::Variant(int32_t i) : impl(new VariantImpl(i)) {} Variant::Variant(int64_t i) : impl(new VariantImpl(i)) {} Variant::Variant(float f) : impl(new VariantImpl(f)) {} Variant::Variant(double d) : impl(new VariantImpl(d)) {} Variant::Variant(const std::string& s) : impl(new VariantImpl(s)) {} Variant::Variant(const char* s) : impl(new VariantImpl(std::string(s))) {} Variant::Variant(const Map& m) : impl(new VariantImpl(m)) {} Variant::Variant(const List& l) : impl(new VariantImpl(l)) {} Variant::Variant(const Variant& v) : impl(VariantImpl::create(v)) {} Variant::Variant(const Uuid& u) : impl(new VariantImpl(u)) {} Variant::~Variant() { if (impl) delete impl; } void Variant::reset() { if (impl) delete impl; impl = 0; } Variant& Variant::operator=(bool b) { if (impl) delete impl; impl = new VariantImpl(b); return *this; } Variant& Variant::operator=(uint8_t i) { if (impl) delete impl; impl = new VariantImpl(i); return *this; } Variant& Variant::operator=(uint16_t i) { if (impl) delete impl; impl = new VariantImpl(i); return *this; } Variant& Variant::operator=(uint32_t i) { if (impl) delete impl; impl = new VariantImpl(i); return *this; } Variant& Variant::operator=(uint64_t i) { if (impl) delete impl; impl = new VariantImpl(i); return *this; } Variant& Variant::operator=(int8_t i) { if (impl) delete impl; impl = new VariantImpl(i); return *this; } Variant& Variant::operator=(int16_t i) { if (impl) delete impl; impl = new VariantImpl(i); return *this; } Variant& Variant::operator=(int32_t i) { if (impl) delete impl; impl = new VariantImpl(i); return *this; } Variant& Variant::operator=(int64_t i) { if (impl) delete impl; impl = new VariantImpl(i); return *this; } Variant& Variant::operator=(float f) { if (impl) delete impl; impl = new VariantImpl(f); return *this; } Variant& Variant::operator=(double d) { if (impl) delete impl; impl = new VariantImpl(d); return *this; } Variant& Variant::operator=(const std::string& s) { if (impl) delete impl; impl = new VariantImpl(s); return *this; } Variant& Variant::operator=(const char* s) { if (impl) delete impl; impl = new VariantImpl(std::string(s)); return *this; } Variant& Variant::operator=(const Uuid& u) { if (impl) delete impl; impl = new VariantImpl(u); return *this; } Variant& Variant::operator=(const Map& m) { if (impl) delete impl; impl = new VariantImpl(m); return *this; } Variant& Variant::operator=(const List& l) { if (impl) delete impl; impl = new VariantImpl(l); return *this; } Variant& Variant::operator=(const Variant& v) { if (impl) delete impl; impl = VariantImpl::create(v); return *this; } Variant& Variant::parse(const std::string& s) { operator=(s); try { return operator=(asInt64()); } catch (const InvalidConversion&) {} try { return operator=(asDouble()); } catch (const InvalidConversion&) {} try { return operator=(asBool()); } catch (const InvalidConversion&) {} return *this; } VariantType Variant::getType() const { return impl ? impl->getType() : VAR_VOID; } bool Variant::isVoid() const { return getType() == VAR_VOID; } bool Variant::asBool() const { return impl && impl->asBool(); } uint8_t Variant::asUint8() const { return impl ? impl->asUint8() : 0; } uint16_t Variant::asUint16() const { return impl ? impl->asUint16() : 0; } uint32_t Variant::asUint32() const { return impl ? impl->asUint32() : 0; } uint64_t Variant::asUint64() const { return impl ? impl->asUint64() : 0; } int8_t Variant::asInt8() const { return impl ? impl->asInt8() : 0; } int16_t Variant::asInt16() const { return impl ? impl->asInt16() : 0; } int32_t Variant::asInt32() const { return impl ? impl->asInt32(): 0; } int64_t Variant::asInt64() const { return impl ? impl->asInt64() : 0; } float Variant::asFloat() const { return impl ? impl->asFloat() : 0; } double Variant::asDouble() const { return impl ? impl->asDouble() : 0; } std::string Variant::asString() const { return impl ? impl->asString() : EMPTY; } Uuid Variant::asUuid() const { return impl ? impl->asUuid() : Uuid(); } const Variant::Map& Variant::asMap() const { if (!impl) throw InvalidConversion("Can't convert VOID to MAP"); return impl->asMap(); } Variant::Map& Variant::asMap() { if (!impl) throw InvalidConversion("Can't convert VOID to MAP"); return impl->asMap(); } const Variant::List& Variant::asList() const { if (!impl) throw InvalidConversion("Can't convert VOID to LIST"); return impl->asList(); } Variant::List& Variant::asList() { if (!impl) throw InvalidConversion("Can't convert VOID to LIST"); return impl->asList(); } const std::string& Variant::getString() const { if (!impl) throw InvalidConversion("Can't convert VOID to STRING"); return impl->getString(); } std::string& Variant::getString() { if (!impl) throw InvalidConversion("Can't convert VOID to STRING"); return impl->getString(); } void Variant::setEncoding(const std::string& s) { if (!impl) impl = new VariantImpl(); impl->setEncoding(s); } const std::string& Variant::getEncoding() const { return impl ? impl->getEncoding() : EMPTY; } Variant::operator bool() const { return asBool(); } Variant::operator uint8_t() const { return asUint8(); } Variant::operator uint16_t() const { return asUint16(); } Variant::operator uint32_t() const { return asUint32(); } Variant::operator uint64_t() const { return asUint64(); } Variant::operator int8_t() const { return asInt8(); } Variant::operator int16_t() const { return asInt16(); } Variant::operator int32_t() const { return asInt32(); } Variant::operator int64_t() const { return asInt64(); } Variant::operator float() const { return asFloat(); } Variant::operator double() const { return asDouble(); } Variant::operator std::string() const { return asString(); } Variant::operator Uuid() const { return asUuid(); } std::ostream& operator<<(std::ostream& out, const Variant::Map& map) { out << "{"; for (Variant::Map::const_iterator i = map.begin(); i != map.end(); ++i) { if (i != map.begin()) out << ", "; out << i->first << ":" << i->second; } out << "}"; return out; } std::ostream& operator<<(std::ostream& out, const Variant::List& list) { out << "["; for (Variant::List::const_iterator i = list.begin(); i != list.end(); ++i) { if (i != list.begin()) out << ", "; out << *i; } out << "]"; return out; } std::ostream& operator<<(std::ostream& out, const Variant& value) { switch (value.getType()) { case VAR_MAP: out << value.asMap(); break; case VAR_LIST: out << value.asList(); break; case VAR_VOID: out << ""; break; default: out << value.asString(); break; } return out; } bool operator==(const Variant& a, const Variant& b) { return a.isEqualTo(b); } bool Variant::isEqualTo(const Variant& other) const { return impl && impl->isEqualTo(*other.impl); } }} // namespace qpid::types