You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by gs...@apache.org on 2010/03/18 19:37:28 UTC

svn commit: r924939 - in /qpid/trunk/qpid/cpp: include/qpid/framing/FieldValue.h src/qpid/client/amqp0_10/Codecs.cpp src/qpid/framing/FieldValue.cpp src/qpid/messaging/Variant.cpp src/tests/MessagingSessionTests.cpp src/tests/Variant.cpp

Author: gsim
Date: Thu Mar 18 18:37:28 2010
New Revision: 924939

URL: http://svn.apache.org/viewvc?rev=924939&view=rev
Log:
QPID-2452: Fixed control over the encoding used when sending a string valued variant. The user is currently responsible for correctly setting any encoding (e.g. utf8). If none is specified it will be transfered as an amqp0-10 vbin. Fixed bug preventing correct assignment of encoding in variants.


Modified:
    qpid/trunk/qpid/cpp/include/qpid/framing/FieldValue.h
    qpid/trunk/qpid/cpp/src/qpid/client/amqp0_10/Codecs.cpp
    qpid/trunk/qpid/cpp/src/qpid/framing/FieldValue.cpp
    qpid/trunk/qpid/cpp/src/qpid/messaging/Variant.cpp
    qpid/trunk/qpid/cpp/src/tests/MessagingSessionTests.cpp
    qpid/trunk/qpid/cpp/src/tests/Variant.cpp

Modified: qpid/trunk/qpid/cpp/include/qpid/framing/FieldValue.h
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/include/qpid/framing/FieldValue.h?rev=924939&r1=924938&r2=924939&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/include/qpid/framing/FieldValue.h (original)
+++ qpid/trunk/qpid/cpp/include/qpid/framing/FieldValue.h Thu Mar 18 18:37:28 2010
@@ -335,6 +335,16 @@ class Str16Value : public FieldValue {
     QPID_COMMON_EXTERN Str16Value(const std::string& v);
 };
 
+class Var16Value : public FieldValue {
+  public:
+    QPID_COMMON_EXTERN Var16Value(const std::string& v, uint8_t code);
+};
+
+class Var32Value : public FieldValue {
+  public:
+    QPID_COMMON_EXTERN Var32Value(const std::string& v, uint8_t code);
+};
+
 class Struct32Value : public FieldValue {
   public:
     QPID_COMMON_EXTERN Struct32Value(const std::string& v);

Modified: qpid/trunk/qpid/cpp/src/qpid/client/amqp0_10/Codecs.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/client/amqp0_10/Codecs.cpp?rev=924939&r1=924938&r2=924939&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/client/amqp0_10/Codecs.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/client/amqp0_10/Codecs.cpp Thu Mar 18 18:37:28 2010
@@ -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<Fiel
       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<Fiel
     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> toFieldVal
       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()));

Modified: qpid/trunk/qpid/cpp/src/qpid/framing/FieldValue.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/framing/FieldValue.cpp?rev=924939&r1=924938&r2=924939&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/framing/FieldValue.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/framing/FieldValue.cpp Thu Mar 18 18:37:28 2010
@@ -130,6 +130,21 @@ Str16Value::Str16Value(const std::string
             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,

Modified: qpid/trunk/qpid/cpp/src/qpid/messaging/Variant.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/messaging/Variant.cpp?rev=924939&r1=924938&r2=924939&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/messaging/Variant.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/messaging/Variant.cpp Thu Mar 18 18:37:28 2010
@@ -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) : ty
 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 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());

Modified: qpid/trunk/qpid/cpp/src/tests/MessagingSessionTests.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/MessagingSessionTests.cpp?rev=924939&r1=924938&r2=924939&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/MessagingSessionTests.cpp (original)
+++ qpid/trunk/qpid/cpp/src/tests/MessagingSessionTests.cpp Thu Mar 18 18:37:28 2010
@@ -336,6 +336,12 @@ QPID_AUTO_TEST_CASE(testMapMessage)
     MapContent content(out);
     content["abc"] = "def";
     content["pi"] = 3.14f;
+    Variant utf8("A utf 8 string");
+    utf8.setEncoding("utf8");
+    content["utf8"] = utf8;
+    Variant utf16("\x00\x61\x00\x62\x00\x63");
+    utf16.setEncoding("utf16");
+    content["utf16"] = utf16;
     content.encode();
     sender.send(out);
     Receiver receiver = fix.session.createReceiver(fix.queue);
@@ -343,6 +349,10 @@ QPID_AUTO_TEST_CASE(testMapMessage)
     MapView view(in);
     BOOST_CHECK_EQUAL(view["abc"].asString(), "def");
     BOOST_CHECK_EQUAL(view["pi"].asFloat(), 3.14f);
+    BOOST_CHECK_EQUAL(view["utf8"].asString(), utf8.asString());
+    BOOST_CHECK_EQUAL(view["utf8"].getEncoding(), utf8.getEncoding());
+    BOOST_CHECK_EQUAL(view["utf16"].asString(), utf16.asString());
+    BOOST_CHECK_EQUAL(view["utf16"].getEncoding(), utf16.getEncoding());
     fix.session.acknowledge();
 }
 

Modified: qpid/trunk/qpid/cpp/src/tests/Variant.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/Variant.cpp?rev=924939&r1=924938&r2=924939&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/Variant.cpp (original)
+++ qpid/trunk/qpid/cpp/src/tests/Variant.cpp Thu Mar 18 18:37:28 2010
@@ -178,6 +178,21 @@ QPID_AUTO_TEST_CASE(testIsEqualTo)
     BOOST_CHECK_EQUAL(a, b);
 }
 
+QPID_AUTO_TEST_CASE(testEncoding)
+{
+    Variant a("abc");
+    a.setEncoding("utf8");
+    Variant b = a;
+    Variant map = Variant::Map();
+    map.asMap()["a"] = a;
+    map.asMap()["b"] = b;
+    BOOST_CHECK_EQUAL(a.getEncoding(), std::string("utf8"));
+    BOOST_CHECK_EQUAL(a.getEncoding(), b.getEncoding());
+    BOOST_CHECK_EQUAL(a.getEncoding(), map.asMap()["a"].getEncoding());
+    BOOST_CHECK_EQUAL(b.getEncoding(), map.asMap()["b"].getEncoding());
+    BOOST_CHECK_EQUAL(map.asMap()["a"].getEncoding(), map.asMap()["b"].getEncoding());
+}
+
 QPID_AUTO_TEST_SUITE_END()
 
 }} // namespace qpid::tests



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:commits-subscribe@qpid.apache.org