diff options
Diffstat (limited to 'cpp/src/qpid')
-rw-r--r-- | cpp/src/qpid/client/amqp0_10/Codecs.cpp | 30 | ||||
-rw-r--r-- | cpp/src/qpid/framing/FieldValue.cpp | 15 | ||||
-rw-r--r-- | cpp/src/qpid/messaging/Variant.cpp | 8 |
3 files changed, 47 insertions, 6 deletions
diff --git a/cpp/src/qpid/client/amqp0_10/Codecs.cpp b/cpp/src/qpid/client/amqp0_10/Codecs.cpp index e6d51ae725..3e17fc968b 100644 --- a/cpp/src/qpid/client/amqp0_10/Codecs.cpp +++ b/cpp/src/qpid/client/amqp0_10/Codecs.cpp @@ -25,8 +25,10 @@ #include "qpid/framing/FieldTable.h" #include "qpid/framing/FieldValue.h" #include "qpid/framing/List.h" +#include "qpid/log/Statement.h" #include <algorithm> #include <functional> +#include <limits> using namespace qpid::framing; using namespace qpid::messaging; @@ -39,6 +41,7 @@ namespace { const std::string iso885915("iso-8859-15"); const std::string utf8("utf8"); const std::string utf16("utf16"); +const std::string binary("binary"); const std::string amqp0_10_binary("amqp0-10:binary"); const std::string amqp0_10_bit("amqp0-10:bit"); const std::string amqp0_10_datetime("amqp0-10:datetime"); @@ -163,8 +166,8 @@ Variant toVariant(boost::shared_ptr<FieldValue> in) case 0x96: case 0xa0: case 0xab: - setEncodingFor(out, in->getType()); out = in->get<std::string>(); + setEncodingFor(out, in->getType()); break; case 0xa8: @@ -188,6 +191,28 @@ Variant toVariant(boost::shared_ptr<FieldValue> in) return out; } +boost::shared_ptr<FieldValue> convertString(const std::string& value, const std::string& encoding) +{ + bool large = value.size() > std::numeric_limits<uint16_t>::max(); + if (encoding.empty() || encoding == amqp0_10_binary || encoding == binary) { + if (large) { + return boost::shared_ptr<FieldValue>(new Var32Value(value, 0xa0)); + } else { + return boost::shared_ptr<FieldValue>(new Var16Value(value, 0x90)); + } + } else if (encoding == utf8 && !large) { + return boost::shared_ptr<FieldValue>(new Str16Value(value)); + } else if (encoding == utf16 && !large) { + return boost::shared_ptr<FieldValue>(new Var16Value(value, 0x96)); + } else if (encoding == iso885915 && !large) { + return boost::shared_ptr<FieldValue>(new Var16Value(value, 0x94)); + } else { + //either the string is too large for the encoding in amqp 0-10, or the encoding was not recognised + QPID_LOG(warning, "Could not encode " << value.size() << " byte value as " << encoding << ", encoding as vbin32."); + return boost::shared_ptr<FieldValue>(new Var32Value(value, 0xa0)); + } +} + boost::shared_ptr<FieldValue> toFieldValue(const Variant& in) { boost::shared_ptr<FieldValue> out; @@ -204,8 +229,7 @@ boost::shared_ptr<FieldValue> toFieldValue(const Variant& in) case VAR_INT64: out = boost::shared_ptr<FieldValue>(new Integer64Value(in.asInt64())); break; case VAR_FLOAT: out = boost::shared_ptr<FieldValue>(new FloatValue(in.asFloat())); break; case VAR_DOUBLE: out = boost::shared_ptr<FieldValue>(new DoubleValue(in.asDouble())); break; - //TODO: check encoding (and length?) when deciding what AMQP type to treat string as - case VAR_STRING: out = boost::shared_ptr<FieldValue>(new Str16Value(in.asString())); break; + case VAR_STRING: out = convertString(in.asString(), in.getEncoding()); break; case VAR_UUID: out = boost::shared_ptr<FieldValue>(new UuidValue(in.asUuid().data())); break; case VAR_MAP: out = boost::shared_ptr<FieldValue>(toFieldTableValue(in.asMap())); diff --git a/cpp/src/qpid/framing/FieldValue.cpp b/cpp/src/qpid/framing/FieldValue.cpp index fd911645f4..ce5a50117c 100644 --- a/cpp/src/qpid/framing/FieldValue.cpp +++ b/cpp/src/qpid/framing/FieldValue.cpp @@ -130,6 +130,21 @@ Str16Value::Str16Value(const std::string& v) : reinterpret_cast<const uint8_t*>(v.data()+v.size()))) {} +Var16Value::Var16Value(const std::string& v, uint8_t code) : + FieldValue( + code, + new VariableWidthValue<2>( + reinterpret_cast<const uint8_t*>(v.data()), + reinterpret_cast<const uint8_t*>(v.data()+v.size()))) +{} +Var32Value::Var32Value(const std::string& v, uint8_t code) : + FieldValue( + code, + new VariableWidthValue<4>( + reinterpret_cast<const uint8_t*>(v.data()), + reinterpret_cast<const uint8_t*>(v.data()+v.size()))) +{} + Struct32Value::Struct32Value(const std::string& v) : FieldValue( 0xAB, diff --git a/cpp/src/qpid/messaging/Variant.cpp b/cpp/src/qpid/messaging/Variant.cpp index ba93f160ec..2567b7508b 100644 --- a/cpp/src/qpid/messaging/Variant.cpp +++ b/cpp/src/qpid/messaging/Variant.cpp @@ -20,6 +20,7 @@ */ #include "qpid/messaging/Variant.h" #include "qpid/Msg.h" +#include "qpid/log/Statement.h" #include <boost/format.hpp> #include <boost/lexical_cast.hpp> #include <algorithm> @@ -50,7 +51,7 @@ class VariantImpl VariantImpl(int64_t); VariantImpl(float); VariantImpl(double); - VariantImpl(const std::string&); + VariantImpl(const std::string&, const std::string& encoding=std::string()); VariantImpl(const Variant::Map&); VariantImpl(const Variant::List&); VariantImpl(const Uuid&); @@ -130,7 +131,8 @@ 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) : type(VAR_STRING) { value.v = new std::string(s); } +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); } @@ -448,7 +450,7 @@ VariantImpl* VariantImpl::create(const Variant& v) 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()); + 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()); |