summaryrefslogtreecommitdiff
path: root/cpp/src/qpid
diff options
context:
space:
mode:
authorAndrew Stitcher <astitcher@apache.org>2007-10-16 10:21:20 +0000
committerAndrew Stitcher <astitcher@apache.org>2007-10-16 10:21:20 +0000
commit5113fdd829e956b6836c102c13b83fb8105a7453 (patch)
tree600ada669c06d834c4509ea6c277deeaefc9effa /cpp/src/qpid
parent0ae648d78f3970eb7fc96f000a5ba4f6444e4b6e (diff)
downloadqpid-python-5113fdd829e956b6836c102c13b83fb8105a7453.tar.gz
Implementation of 0-10 field tables
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@585097 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/qpid')
-rw-r--r--cpp/src/qpid/broker/Exchange.cpp4
-rw-r--r--cpp/src/qpid/broker/HeadersExchange.cpp46
-rw-r--r--cpp/src/qpid/broker/Queue.cpp4
-rw-r--r--cpp/src/qpid/framing/AMQFrame.cpp2
-rw-r--r--cpp/src/qpid/framing/BasicHeaderProperties.cpp4
-rw-r--r--cpp/src/qpid/framing/Buffer.cpp101
-rw-r--r--cpp/src/qpid/framing/Buffer.h12
-rw-r--r--cpp/src/qpid/framing/FieldTable.cpp80
-rw-r--r--cpp/src/qpid/framing/FieldTable.h36
-rw-r--r--cpp/src/qpid/framing/FieldValue.cpp256
-rw-r--r--cpp/src/qpid/framing/FieldValue.h177
-rw-r--r--cpp/src/qpid/framing/Value.cpp4
12 files changed, 605 insertions, 121 deletions
diff --git a/cpp/src/qpid/broker/Exchange.cpp b/cpp/src/qpid/broker/Exchange.cpp
index 04407eb774..2d5cb09d7c 100644
--- a/cpp/src/qpid/broker/Exchange.cpp
+++ b/cpp/src/qpid/broker/Exchange.cpp
@@ -35,7 +35,7 @@ Exchange::shared_ptr Exchange::decode(ExchangeRegistry& exchanges, Buffer& buffe
buffer.getShortString(name);
bool durable(buffer.getOctet());
buffer.getShortString(type);
- buffer.getFieldTable(args);
+ buffer.get(args);
return exchanges.declare(name, type, durable, args).first;
}
@@ -45,7 +45,7 @@ void Exchange::encode(Buffer& buffer) const
buffer.putShortString(name);
buffer.putOctet(durable);
buffer.putShortString(getType());
- buffer.putFieldTable(args);
+ buffer.put(args);
}
uint32_t Exchange::encodedSize() const
diff --git a/cpp/src/qpid/broker/HeadersExchange.cpp b/cpp/src/qpid/broker/HeadersExchange.cpp
index 955b975ffb..55cdb73ac1 100644
--- a/cpp/src/qpid/broker/HeadersExchange.cpp
+++ b/cpp/src/qpid/broker/HeadersExchange.cpp
@@ -19,7 +19,7 @@
*
*/
#include "HeadersExchange.h"
-#include "qpid/framing/Value.h"
+#include "qpid/framing/FieldValue.h"
#include "qpid/QpidError.h"
#include <algorithm>
@@ -35,8 +35,8 @@ using namespace qpid::sys;
using namespace qpid::broker;
namespace {
- const std::string all("all");
- const std::string any("any");
+ const StringValue all("all");
+ const StringValue any("any");
const std::string x_match("x-match");
}
@@ -45,8 +45,8 @@ HeadersExchange::HeadersExchange(const std::string& _name, bool _durable, const
bool HeadersExchange::bind(Queue::shared_ptr queue, const string& /*routingKey*/, const FieldTable* args){
RWlock::ScopedWlock locker(lock);
- std::string what = args->getString("x-match");
- if (what != all && what != any) {
+ FieldTable::ValuePtr what = args->get(x_match);
+ if (*what != all && *what != any) {
THROW_QPID_ERROR(PROTOCOL_ERROR, "Invalid x-match value binding to headers exchange.");
}
Binding binding(*args, queue);
@@ -98,8 +98,8 @@ const std::string HeadersExchange::typeName("headers");
namespace
{
- bool match_values(const Value& bind, const Value& msg) {
- return dynamic_cast<const EmptyValue*>(&bind) || bind == msg;
+ bool match_values(const FieldValue& bind, const FieldValue& msg) {
+ return bind.empty() || bind == msg;
}
}
@@ -107,29 +107,31 @@ namespace
bool HeadersExchange::match(const FieldTable& bind, const FieldTable& msg) {
typedef FieldTable::ValueMap Map;
- std::string what = bind.getString(x_match);
- if (what == all) {
- for (Map::const_iterator i = bind.getMap().begin();
- i != bind.getMap().end();
+ FieldTable::ValuePtr what = bind.get(x_match);
+ if (!what) {
+ return false;
+ } else if (*what == all) {
+ for (Map::const_iterator i = bind.begin();
+ i != bind.end();
++i)
{
if (i->first != x_match)
{
- Map::const_iterator j = msg.getMap().find(i->first);
- if (j == msg.getMap().end()) return false;
+ Map::const_iterator j = msg.find(i->first);
+ if (j == msg.end()) return false;
if (!match_values(*(i->second), *(j->second))) return false;
}
}
return true;
- } else if (what == any) {
- for (Map::const_iterator i = bind.getMap().begin();
- i != bind.getMap().end();
+ } else if (*what == any) {
+ for (Map::const_iterator i = bind.begin();
+ i != bind.end();
++i)
{
if (i->first != x_match)
{
- Map::const_iterator j = msg.getMap().find(i->first);
- if (j != msg.getMap().end()) {
+ Map::const_iterator j = msg.find(i->first);
+ if (j != msg.end()) {
if (match_values(*(i->second), *(j->second))) return true;
}
}
@@ -142,12 +144,12 @@ bool HeadersExchange::match(const FieldTable& bind, const FieldTable& msg) {
bool HeadersExchange::equal(const FieldTable& a, const FieldTable& b) {
typedef FieldTable::ValueMap Map;
- for (Map::const_iterator i = a.getMap().begin();
- i != a.getMap().end();
+ for (Map::const_iterator i = a.begin();
+ i != a.end();
++i)
{
- Map::const_iterator j = b.getMap().find(i->first);
- if (j == b.getMap().end()) return false;
+ Map::const_iterator j = b.find(i->first);
+ if (j == b.end()) return false;
if (!match_values(*(i->second), *(j->second))) return false;
}
return true;
diff --git a/cpp/src/qpid/broker/Queue.cpp b/cpp/src/qpid/broker/Queue.cpp
index 3065041424..e4a6449e08 100644
--- a/cpp/src/qpid/broker/Queue.cpp
+++ b/cpp/src/qpid/broker/Queue.cpp
@@ -413,7 +413,7 @@ void Queue::setPersistenceId(uint64_t _persistenceId) const
void Queue::encode(framing::Buffer& buffer) const
{
buffer.putShortString(name);
- buffer.putFieldTable(settings);
+ buffer.put(settings);
}
uint32_t Queue::encodedSize() const
@@ -426,7 +426,7 @@ Queue::shared_ptr Queue::decode(QueueRegistry& queues, framing::Buffer& buffer)
string name;
buffer.getShortString(name);
std::pair<Queue::shared_ptr, bool> result = queues.declare(name, true);
- buffer.getFieldTable(result.first->settings);
+ buffer.get(result.first->settings);
result.first->configure(result.first->settings);
return result.first;
}
diff --git a/cpp/src/qpid/framing/AMQFrame.cpp b/cpp/src/qpid/framing/AMQFrame.cpp
index 9140f16f7a..abd33c4158 100644
--- a/cpp/src/qpid/framing/AMQFrame.cpp
+++ b/cpp/src/qpid/framing/AMQFrame.cpp
@@ -157,7 +157,7 @@ void AMQFrame::decodeBody(Buffer& buffer, uint32_t size, uint8_t type)
std::ostream& operator<<(std::ostream& out, const AMQFrame& f)
{
return out << "Frame["
- //<< "B=" << f.getBof() << "E=" << f.getEof() << "b=" << f.getBos() << "e=" << f.getEos() << "; "
+ << (f.getBof() ? "B" : "") << (f.getEof() ? "E" : "") << (f.getBos() ? "b" : "") << (f.getEos() ? "e" : "") << "; "
<< "channel=" << f.getChannel() << "; " << *f.getBody()
<< "]";
}
diff --git a/cpp/src/qpid/framing/BasicHeaderProperties.cpp b/cpp/src/qpid/framing/BasicHeaderProperties.cpp
index 7d933d0db8..9d572787ae 100644
--- a/cpp/src/qpid/framing/BasicHeaderProperties.cpp
+++ b/cpp/src/qpid/framing/BasicHeaderProperties.cpp
@@ -55,7 +55,7 @@ void qpid::framing::BasicHeaderProperties::encode(qpid::framing::Buffer& buffer)
if(contentType.length() > 0) buffer.putShortString(contentType);
if(contentEncoding.length() > 0) buffer.putShortString(contentEncoding);
- if(headers.count() > 0) buffer.putFieldTable(headers);
+ if(headers.count() > 0) buffer.put(headers);
if(deliveryMode != 0) buffer.putOctet(deliveryMode);
if(priority != 0) buffer.putOctet(priority);
if(correlationId.length() > 0) buffer.putShortString(correlationId);
@@ -74,7 +74,7 @@ void qpid::framing::BasicHeaderProperties::decode(qpid::framing::Buffer& buffer,
uint16_t flags = buffer.getShort();
if(flags & (1 << 15)) buffer.getShortString(contentType);
if(flags & (1 << 14)) buffer.getShortString(contentEncoding);
- if(flags & (1 << 13)) buffer.getFieldTable(headers);
+ if(flags & (1 << 13)) buffer.get(headers);
if(flags & (1 << 12)) deliveryMode = DeliveryMode(buffer.getOctet());
if(flags & (1 << 11)) priority = buffer.getOctet();
if(flags & (1 << 10)) buffer.getShortString(correlationId);
diff --git a/cpp/src/qpid/framing/Buffer.cpp b/cpp/src/qpid/framing/Buffer.cpp
index 930e3162c1..758d0b5f3c 100644
--- a/cpp/src/qpid/framing/Buffer.cpp
+++ b/cpp/src/qpid/framing/Buffer.cpp
@@ -22,35 +22,39 @@
#include "FramingContent.h"
#include "FieldTable.h"
-qpid::framing::Buffer::Buffer(char* _data, uint32_t _size)
+namespace qpid {
+
+namespace framing {
+
+Buffer::Buffer(char* _data, uint32_t _size)
: size(_size), data(_data), position(0) {
}
-void qpid::framing::Buffer::record(){
+void Buffer::record(){
r_position = position;
}
-void qpid::framing::Buffer::restore(){
+void Buffer::restore(){
position = r_position;
}
-uint32_t qpid::framing::Buffer::available(){
+uint32_t Buffer::available(){
return size - position;
}
///////////////////////////////////////////////////
-void qpid::framing::Buffer::putOctet(uint8_t i){
+void Buffer::putOctet(uint8_t i){
data[position++] = i;
}
-void qpid::framing::Buffer::putShort(uint16_t i){
+void Buffer::putShort(uint16_t i){
uint16_t b = i;
data[position++] = (uint8_t) (0xFF & (b >> 8));
data[position++] = (uint8_t) (0xFF & b);
}
-void qpid::framing::Buffer::putLong(uint32_t i){
+void Buffer::putLong(uint32_t i){
uint32_t b = i;
data[position++] = (uint8_t) (0xFF & (b >> 24));
data[position++] = (uint8_t) (0xFF & (b >> 16));
@@ -58,25 +62,25 @@ void qpid::framing::Buffer::putLong(uint32_t i){
data[position++] = (uint8_t) (0xFF & b);
}
-void qpid::framing::Buffer::putLongLong(uint64_t i){
+void Buffer::putLongLong(uint64_t i){
uint32_t hi = i >> 32;
uint32_t lo = i;
putLong(hi);
putLong(lo);
}
-uint8_t qpid::framing::Buffer::getOctet(){
+uint8_t Buffer::getOctet(){
return (uint8_t) data[position++];
}
-uint16_t qpid::framing::Buffer::getShort(){
+uint16_t Buffer::getShort(){
uint16_t hi = (unsigned char) data[position++];
hi = hi << 8;
hi |= (unsigned char) data[position++];
return hi;
}
-uint32_t qpid::framing::Buffer::getLong(){
+uint32_t Buffer::getLong(){
uint32_t a = (unsigned char) data[position++];
uint32_t b = (unsigned char) data[position++];
uint32_t c = (unsigned char) data[position++];
@@ -88,73 +92,98 @@ uint32_t qpid::framing::Buffer::getLong(){
return a;
}
-uint64_t qpid::framing::Buffer::getLongLong(){
+uint64_t Buffer::getLongLong(){
uint64_t hi = getLong();
uint64_t lo = getLong();
hi = hi << 32;
return hi | lo;
}
+template <>
+uint64_t Buffer::getUInt<1>() {
+ return getOctet();
+}
+
+template <>
+uint64_t Buffer::getUInt<2>() {
+ return getShort();
+}
+
+template <>
+uint64_t Buffer::getUInt<4>() {
+ return getLong();
+}
+
+template <>
+uint64_t Buffer::getUInt<8>() {
+ return getLongLong();
+}
+
+template <>
+void Buffer::putUInt<1>(uint64_t i) {
+ putOctet(i);
+}
+
+template <>
+void Buffer::putUInt<2>(uint64_t i) {
+ putShort(i);
+}
+
+template <>
+void Buffer::putUInt<4>(uint64_t i) {
+ putLong(i);
+}
+
+template <>
+void Buffer::putUInt<8>(uint64_t i) {
+ putLongLong(i);
+}
-void qpid::framing::Buffer::putShortString(const string& s){
+void Buffer::putShortString(const string& s){
uint8_t len = s.length();
putOctet(len);
s.copy(data + position, len);
position += len;
}
-void qpid::framing::Buffer::putLongString(const string& s){
+void Buffer::putLongString(const string& s){
uint32_t len = s.length();
putLong(len);
s.copy(data + position, len);
position += len;
}
-void qpid::framing::Buffer::getShortString(string& s){
+void Buffer::getShortString(string& s){
uint8_t len = getOctet();
s.assign(data + position, len);
position += len;
}
-void qpid::framing::Buffer::getLongString(string& s){
+void Buffer::getLongString(string& s){
uint32_t len = getLong();
s.assign(data + position, len);
position += len;
}
-void qpid::framing::Buffer::putFieldTable(const FieldTable& t){
- t.encode(*this);
-}
-
-void qpid::framing::Buffer::getFieldTable(FieldTable& t){
- t.decode(*this);
-}
-
-void qpid::framing::Buffer::putContent(const Content& c){
- c.encode(*this);
-}
-
-void qpid::framing::Buffer::getContent(Content& c){
- c.decode(*this);
-}
-
-void qpid::framing::Buffer::putRawData(const string& s){
+void Buffer::putRawData(const string& s){
uint32_t len = s.length();
s.copy(data + position, len);
position += len;
}
-void qpid::framing::Buffer::getRawData(string& s, uint32_t len){
+void Buffer::getRawData(string& s, uint32_t len){
s.assign(data + position, len);
position += len;
}
-void qpid::framing::Buffer::putRawData(const uint8_t* s, size_t len){
+void Buffer::putRawData(const uint8_t* s, size_t len){
memcpy(data + position, s, len);
position += len;
}
-void qpid::framing::Buffer::getRawData(uint8_t* s, size_t len){
+void Buffer::getRawData(uint8_t* s, size_t len){
memcpy(s, data + position, len);
position += len;
}
+
+}}
diff --git a/cpp/src/qpid/framing/Buffer.h b/cpp/src/qpid/framing/Buffer.h
index b8f3ddb6a9..3b2e611881 100644
--- a/cpp/src/qpid/framing/Buffer.h
+++ b/cpp/src/qpid/framing/Buffer.h
@@ -53,18 +53,18 @@ public:
uint16_t getShort();
uint32_t getLong();
uint64_t getLongLong();
+
+ template <int n>
+ uint64_t getUInt();
+
+ template <int n>
+ void putUInt(uint64_t);
void putShortString(const string& s);
void putLongString(const string& s);
void getShortString(string& s);
void getLongString(string& s);
- void putFieldTable(const FieldTable& t);
- void getFieldTable(FieldTable& t);
-
- void putContent(const Content& c);
- void getContent(Content& c);
-
void putRawData(const string& s);
void getRawData(string& s, uint32_t size);
diff --git a/cpp/src/qpid/framing/FieldTable.cpp b/cpp/src/qpid/framing/FieldTable.cpp
index 3eb4e849bc..f30b49f739 100644
--- a/cpp/src/qpid/framing/FieldTable.cpp
+++ b/cpp/src/qpid/framing/FieldTable.cpp
@@ -21,7 +21,7 @@
#include "FieldTable.h"
#include "qpid/QpidError.h"
#include "Buffer.h"
-#include "Value.h"
+#include "FieldValue.h"
#include <assert.h>
namespace qpid {
@@ -32,8 +32,8 @@ FieldTable::~FieldTable() {}
uint32_t FieldTable::size() const {
uint32_t len(4);
for(ValueMap::const_iterator i = values.begin(); i != values.end(); ++i) {
- // 2 = shortstr_len_byyte + type_char_byte
- len += 2 + (i->first).size() + (i->second)->size();
+ // shortstr_len_byte + key size + value size
+ len += 1 + (i->first).size() + (i->second)->size();
}
return len;
}
@@ -51,15 +51,19 @@ std::ostream& operator<<(std::ostream& out, const FieldTable::ValueMap::value_ty
std::ostream& operator<<(std::ostream& out, const FieldTable& t) {
out << "{";
- FieldTable::ValueMap::const_iterator i = t.getMap().begin();
- if (i != t.getMap().end()) out << *i++;
- while (i != t.getMap().end())
+ FieldTable::ValueMap::const_iterator i = t.begin();
+ if (i != t.end()) out << *i++;
+ while (i != t.end())
{
out << "," << *i++;
}
return out << "}";
}
+void FieldTable::set(const std::string& name, const ValuePtr& value){
+ values[name] = value;
+}
+
void FieldTable::setString(const std::string& name, const std::string& value){
values[name] = ValuePtr(new StringValue(value));
}
@@ -76,43 +80,51 @@ void FieldTable::setTable(const std::string& name, const FieldTable& value){
values[name] = ValuePtr(new FieldTableValue(value));
}
+FieldTable::ValuePtr FieldTable::get(const std::string& name) const
+{
+ ValuePtr value;
+ ValueMap::const_iterator i = values.find(name);
+ if ( i!=values.end() )
+ value = i->second;
+ return value;
+}
+
namespace {
-template <class T> T default_value() { return T(); }
-template <> int default_value<int>() { return 0; }
-template <> uint64_t default_value<uint64_t>() { return 0; }
+ template <class T> T default_value() { return T(); }
+ template <> int default_value<int>() { return 0; }
+ template <> uint64_t default_value<uint64_t>() { return 0; }
}
template <class T>
-T FieldTable::getValue(const std::string& name) const
+T getValue(const FieldTable::ValuePtr value)
{
- ValueMap::const_iterator i = values.find(name);
- if (i == values.end()) return default_value<T>();
- const ValueOps<T> *vt = dynamic_cast<const ValueOps<T>*>(i->second.get());
- return vt->getValue();
-}
+ if (!value || !value->convertsTo<T>())
+ return default_value<T>();
-std::string FieldTable::getString(const std::string& name) const {
- return getValue<std::string>(name);
+ return value->get<T>();
}
-int FieldTable::getInt(const std::string& name) const {
- return getValue<int>(name);
-}
+//std::string FieldTable::getString(const std::string& name) const {
+// return getValue<std::string>(name);
+//}
-uint64_t FieldTable::getTimestamp(const std::string& name) const {
- return getValue<uint64_t>(name);
+int FieldTable::getInt(const std::string& name) const {
+ return getValue<int>(get(name));
}
-void FieldTable::getTable(const std::string& name, FieldTable& value) const {
- value = getValue<FieldTable>(name);
-}
+//uint64_t FieldTable::getTimestamp(const std::string& name) const {
+// return getValue<uint64_t>(name);
+//}
+//
+//void FieldTable::getTable(const std::string& name, FieldTable& value) const {
+// value = getValue<FieldTable>(name);
+//}
void FieldTable::encode(Buffer& buffer) const{
buffer.putLong(size() - 4);
for (ValueMap::const_iterator i = values.begin(); i!=values.end(); ++i) {
buffer.putShortString(i->first);
- buffer.putOctet(i->second->getType());
- i->second->encode(buffer);
+ i->second->encode(buffer);
}
}
@@ -124,9 +136,11 @@ void FieldTable::decode(Buffer& buffer){
uint32_t leftover = available - len;
while(buffer.available() > leftover){
std::string name;
+ ValuePtr value(new FieldValue);
+
buffer.getShortString(name);
- std::auto_ptr<Value> value(Value::decode_value(buffer));
- values[name] = ValuePtr(value.release());
+ value->decode(buffer);
+ values[name] = ValuePtr(value);
}
}
@@ -141,10 +155,10 @@ bool FieldTable::operator==(const FieldTable& x) const {
return true;
}
-void FieldTable::erase(const std::string& name)
-{
- values.erase(values.find(name));
-}
+//void FieldTable::erase(const std::string& name)
+//{
+// values.erase(values.find(name));
+//}
}
}
diff --git a/cpp/src/qpid/framing/FieldTable.h b/cpp/src/qpid/framing/FieldTable.h
index 2be3e6d3ff..a3e01a968e 100644
--- a/cpp/src/qpid/framing/FieldTable.h
+++ b/cpp/src/qpid/framing/FieldTable.h
@@ -34,7 +34,7 @@ namespace qpid {
*/
namespace framing {
-class Value;
+class FieldValue;
class Buffer;
/**
@@ -46,38 +46,44 @@ class Buffer;
class FieldTable
{
public:
- typedef boost::shared_ptr<Value> ValuePtr;
+ typedef boost::shared_ptr<FieldValue> ValuePtr;
typedef std::map<std::string, ValuePtr> ValueMap;
~FieldTable();
uint32_t size() const;
+ void encode(Buffer& buffer) const;
+ void decode(Buffer& buffer);
+
int count() const;
+ void set(const std::string& name, const ValuePtr& value);
+ ValuePtr get(const std::string& name) const;
+
void setString(const std::string& name, const std::string& value);
void setInt(const std::string& name, int value);
void setTimestamp(const std::string& name, uint64_t value);
void setTable(const std::string& name, const FieldTable& value);
//void setDecimal(string& name, xxx& value);
- std::string getString(const std::string& name) const;
+
+// std::string getString(const std::string& name) const;
int getInt(const std::string& name) const;
- uint64_t getTimestamp(const std::string& name) const;
- void getTable(const std::string& name, FieldTable& value) const;
- //void getDecimal(string& name, xxx& value);
- void erase(const std::string& name);
+// uint64_t getTimestamp(const std::string& name) const;
+// void getTable(const std::string& name, FieldTable& value) const;
+// //void getDecimal(string& name, xxx& value);
+// //void erase(const std::string& name);
- void encode(Buffer& buffer) const;
- void decode(Buffer& buffer);
bool operator==(const FieldTable& other) const;
- // TODO aconway 2006-09-26: Yeuch! Rework FieldTable to have
- // a map-like interface.
- const ValueMap& getMap() const { return values; }
- ValueMap& getMap() { return values; }
+ // Map-like interface.
+ // TODO: may need to duplicate into versions that return mutable iterator
+ ValueMap::const_iterator begin() const { return values.begin(); }
+ ValueMap::const_iterator end() const { return values.end(); }
+ ValueMap::const_iterator find(const std::string& s) const { return values.find(s); }
private:
- friend std::ostream& operator<<(std::ostream& out, const FieldTable& body);
ValueMap values;
- template<class T> T getValue(const std::string& name) const;
+
+ friend std::ostream& operator<<(std::ostream& out, const FieldTable& body);
};
class FieldNotFoundException{};
diff --git a/cpp/src/qpid/framing/FieldValue.cpp b/cpp/src/qpid/framing/FieldValue.cpp
new file mode 100644
index 0000000000..a43c0710ae
--- /dev/null
+++ b/cpp/src/qpid/framing/FieldValue.cpp
@@ -0,0 +1,256 @@
+/*
+ *
+ * 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 "FieldValue.h"
+#include "Buffer.h"
+#include "qpid/QpidError.h"
+
+
+namespace qpid {
+namespace framing {
+
+/*
+ * Specialisations for construction from integers
+ */
+template<>
+FixedWidthValue<8>::FixedWidthValue(uint64_t v)
+{
+ octets[7] = (uint8_t) (0xFF & v); v >>= 8;
+ octets[6] = (uint8_t) (0xFF & v); v >>= 8;
+ octets[5] = (uint8_t) (0xFF & v); v >>= 8;
+ octets[4] = (uint8_t) (0xFF & v); v >>= 8;
+ octets[3] = (uint8_t) (0xFF & v); v >>= 8;
+ octets[2] = (uint8_t) (0xFF & v); v >>= 8;
+ octets[1] = (uint8_t) (0xFF & v); v >>= 8;
+ octets[0] = (uint8_t) (0xFF & v);
+}
+
+template<>
+FixedWidthValue<4>::FixedWidthValue(uint64_t v)
+{
+ octets[3] = (uint8_t) (0xFF & v); v >>= 8;
+ octets[2] = (uint8_t) (0xFF & v); v >>= 8;
+ octets[1] = (uint8_t) (0xFF & v); v >>= 8;
+ octets[0] = (uint8_t) (0xFF & v);
+}
+
+template<>
+FixedWidthValue<2>::FixedWidthValue(uint64_t v)
+{
+ octets[1] = (uint8_t) (0xFF & v); v >>= 8;
+ octets[0] = (uint8_t) (0xFF & v);
+}
+
+template<>
+FixedWidthValue<1>::FixedWidthValue(uint64_t v)
+{
+ octets[0] = (uint8_t) (0xFF & v);
+}
+
+/*
+ * Specialisations for turning into integers
+ */
+template<>
+int64_t FixedWidthValue<8>::getInt() const
+{
+ int64_t v = 0;
+ v |= octets[0]; v <<= 8;
+ v |= octets[1]; v <<= 8;
+ v |= octets[2]; v <<= 8;
+ v |= octets[3]; v <<= 8;
+ v |= octets[4]; v <<= 8;
+ v |= octets[5]; v <<= 8;
+ v |= octets[6]; v <<= 8;
+ v |= octets[7];
+ return v;
+}
+
+template<>
+int64_t FixedWidthValue<4>::getInt() const
+{
+ int64_t v = 0;
+ v |= octets[0]; v <<= 8;
+ v |= octets[1]; v <<= 8;
+ v |= octets[2]; v <<= 8;
+ v |= octets[3];
+ return v;
+}
+
+template<>
+int64_t FixedWidthValue<2>::getInt() const
+{
+ int64_t v = 0;
+ v |= octets[0]; v <<= 8;
+ v |= octets[1];
+ return v;
+}
+
+template<>
+int64_t FixedWidthValue<1>::getInt() const
+{
+ int64_t v = 0;
+ v |= octets[0];
+ return v;
+}
+
+/*
+ * Specialisations for convertion to int predicate
+ */
+template<>
+bool FixedWidthValue<8>::convertsToInt() const
+{
+ return true;
+}
+
+template<>
+bool FixedWidthValue<4>::convertsToInt() const
+{
+ return true;
+}
+
+template<>
+bool FixedWidthValue<2>::convertsToInt() const
+{
+ return true;
+}
+
+template<>
+bool FixedWidthValue<1>::convertsToInt() const
+{
+ return true;
+}
+
+void FieldValue::decode(Buffer& buffer)
+{
+ typeOctet = buffer.getOctet();
+
+ uint8_t lenType = typeOctet >> 4;
+ switch(lenType){
+ case 0:
+ data.reset(new FixedWidthValue<1>());
+ break;
+ case 1:
+ data.reset(new FixedWidthValue<2>());
+ break;
+ case 2:
+ data.reset(new FixedWidthValue<4>());
+ break;
+ case 3:
+ data.reset(new FixedWidthValue<8>());
+ break;
+ case 4:
+ data.reset(new FixedWidthValue<16>());
+ break;
+ case 5:
+ data.reset(new FixedWidthValue<32>());
+ break;
+ case 6:
+ data.reset(new FixedWidthValue<64>());
+ break;
+ case 7:
+ data.reset(new FixedWidthValue<128>());
+ break;
+ case 8:
+ data.reset(new VariableWidthValue<1>());
+ break;
+ case 9:
+ data.reset(new VariableWidthValue<2>());
+ break;
+ case 0xA:
+ data.reset(new VariableWidthValue<4>());
+ break;
+ case 0xC:
+ data.reset(new FixedWidthValue<5>());
+ break;
+ case 0xD:
+ data.reset(new FixedWidthValue<9>());
+ break;
+ case 0xF:
+ data.reset(new FixedWidthValue<0>());
+ break;
+ default:
+ std::stringstream out;
+ out << "Unknown field table value type: " << typeOctet;
+ THROW_QPID_ERROR(FRAMING_ERROR, out.str());
+ }
+ data->decode(buffer);
+}
+
+template<>
+bool FieldValue::convertsTo<int>() const
+{
+ return data->convertsToInt();
+}
+
+template<>
+bool FieldValue::convertsTo<string>() const
+{
+ return data->convertsToString();
+}
+
+template<>
+int FieldValue::get<int>() const
+{
+ return data->getInt();
+}
+
+template<>
+std::string FieldValue::get<std::string>() const
+{
+ return data->getString();
+}
+
+void FieldValue::encode(Buffer& buffer)
+{
+ buffer.putOctet(typeOctet);
+ data->encode(buffer);
+}
+
+bool FieldValue::operator==(const FieldValue& v) const
+{
+ return
+ typeOctet == v.typeOctet &&
+ *data == *v.data;
+}
+
+StringValue::StringValue(const std::string& v) :
+ FieldValue(
+ 0xA4,
+ new VariableWidthValue<4>(
+ reinterpret_cast<const uint8_t*>(v.data()),
+ reinterpret_cast<const uint8_t*>(v.data()+v.size())))
+{
+}
+
+IntegerValue::IntegerValue(int v) :
+ FieldValue(0x21, new FixedWidthValue<4>(v))
+{
+}
+
+TimeValue::TimeValue(uint64_t v) :
+ FieldValue(0x32, new FixedWidthValue<8>(v))
+{
+}
+
+FieldTableValue::FieldTableValue(const FieldTable&) : FieldValue()
+{
+}
+
+}}
diff --git a/cpp/src/qpid/framing/FieldValue.h b/cpp/src/qpid/framing/FieldValue.h
new file mode 100644
index 0000000000..b26021d6fa
--- /dev/null
+++ b/cpp/src/qpid/framing/FieldValue.h
@@ -0,0 +1,177 @@
+#ifndef _framing_FieldValue_h
+#define _framing_FieldValue_h
+/*
+ *
+ * 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 "Buffer.h"
+#include "amqp_types.h"
+
+#include <iostream>
+#include <memory>
+#include <vector>
+
+namespace qpid {
+namespace framing {
+
+/**
+ * Value that can appear in an AMQP field table
+ *
+ * \ingroup clientapi
+ */
+class FieldValue {
+ public:
+ /*
+ * Abstract type for content of different types
+ */
+ class Data {
+ public:
+ virtual ~Data() {};
+ virtual uint32_t size() const = 0;
+ virtual void encode(Buffer& buffer) = 0;
+ virtual void decode(Buffer& buffer) = 0;
+ virtual bool operator==(const Data&) const = 0;
+
+ virtual bool convertsToInt() const { return false; }
+ virtual bool convertsToString() const { return false; }
+ virtual int64_t getInt() const { return 0; }
+ virtual std::string getString() const { return ""; }
+
+ virtual void print(std::ostream& out) const = 0;
+ };
+
+ FieldValue(): data(0) {};
+ // Default assignment operator is fine
+ uint32_t size() const { return 1 + data->size(); };
+ bool empty() const { return data.get() == 0; }
+ void encode(Buffer& buffer);
+ void decode(Buffer& buffer);
+ bool operator==(const FieldValue&) const;
+ bool operator!=(const FieldValue& v) const { return !(*this == v); }
+ void print(std::ostream& out) const { out << "(0x" << std::hex << int(typeOctet) << ")"; data->print(out); }
+
+ template <typename T> bool convertsTo() const { return false; }
+ template <typename T> T get() const;
+
+ protected:
+ FieldValue(uint8_t t, Data* d): typeOctet(t), data(d) {}
+
+ private:
+ uint8_t typeOctet;
+ std::auto_ptr<Data> data;
+};
+
+inline std::ostream& operator<<(std::ostream& out, const FieldValue& v) {
+ v.print(out);
+ return out;
+}
+
+template <int width>
+class FixedWidthValue : public FieldValue::Data {
+ uint8_t octets[width];
+
+ public:
+ FixedWidthValue() {}
+ FixedWidthValue(const uint8_t (&data)[width]) : octets(data) {}
+ FixedWidthValue(uint64_t v);
+ uint32_t size() const { return width; }
+ void encode(Buffer& buffer) { buffer.putRawData(octets, width); }
+ void decode(Buffer& buffer) { buffer.getRawData(octets, width); }
+ bool operator==(const Data& d) const {
+ const FixedWidthValue<width>* rhs = dynamic_cast< const FixedWidthValue<width>* >(&d);
+ if (rhs == 0) return false;
+ else return std::equal(&octets[0], &octets[width], &rhs->octets[0]);
+ }
+
+ bool convertsToInt() const { return false; }
+ int64_t getInt() const { return 0; }
+
+ void print(std::ostream& o) const { o << "F" << width << ":"; };
+};
+
+template <>
+class FixedWidthValue<0> : public FieldValue::Data {
+ public:
+ // Implicit default constructor is fine
+ uint32_t size() const { return 0; }
+ void encode(Buffer&) {};
+ void decode(Buffer&) {};
+ bool operator==(const Data& d) const {
+ const FixedWidthValue<0>* rhs = dynamic_cast< const FixedWidthValue<0>* >(&d);
+ return rhs != 0;
+ }
+ void print(std::ostream& o) const { o << "F0"; };
+};
+
+template <int lenwidth>
+class VariableWidthValue : public FieldValue::Data {
+ std::vector<uint8_t> octets;
+
+ public:
+ VariableWidthValue() {}
+ VariableWidthValue(const std::vector<uint8_t>& data) : octets(data) {}
+ VariableWidthValue(const uint8_t* start, const uint8_t* end) : octets(start, end) {}
+ uint32_t size() const { return lenwidth + octets.size(); }
+ void encode(Buffer& buffer) {
+ buffer.putUInt<lenwidth>(octets.size());
+ buffer.putRawData(&octets[0], octets.size());
+ };
+ void decode(Buffer& buffer) {
+ uint32_t len = buffer.getUInt<lenwidth>();
+ octets.resize(len);
+ buffer.getRawData(&octets[0], len);
+ }
+ bool operator==(const Data& d) const {
+ const VariableWidthValue<lenwidth>* rhs = dynamic_cast< const VariableWidthValue<lenwidth>* >(&d);
+ if (rhs == 0) return false;
+ else return octets==rhs->octets;
+ }
+ void print(std::ostream& o) const { o << "V" << lenwidth << ":" << octets.size() << ":"; };
+};
+
+/*
+ * Basic string value encodes as iso-8859-15 with 32 bit length
+ */
+class StringValue : public FieldValue {
+ public:
+ StringValue(const std::string& v);
+};
+
+/*
+ * Basic integer value encodes as signed 32 bit
+ */
+class IntegerValue : public FieldValue {
+ public:
+ IntegerValue(int v);
+};
+
+class TimeValue : public FieldValue {
+ public:
+ TimeValue(uint64_t v);
+};
+
+class FieldTableValue : public FieldValue {
+ public:
+ FieldTableValue(const FieldTable&);
+};
+
+}} // qpid::framing
+
+#endif
diff --git a/cpp/src/qpid/framing/Value.cpp b/cpp/src/qpid/framing/Value.cpp
index 3e3cc4cbd5..a9f316667f 100644
--- a/cpp/src/qpid/framing/Value.cpp
+++ b/cpp/src/qpid/framing/Value.cpp
@@ -59,10 +59,10 @@ void DecimalValue::decode(Buffer& buffer){
}
void FieldTableValue::encode(Buffer& buffer){
- buffer.putFieldTable(value);
+ buffer.put(value);
}
void FieldTableValue::decode(Buffer& buffer){
- buffer.getFieldTable(value);
+ buffer.get(value);
}
std::auto_ptr<Value> Value::decode_value(Buffer& buffer)