00001 #ifndef _framing_FieldValue_h
00002 #define _framing_FieldValue_h
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "qpid/Exception.h"
00025 #include "Buffer.h"
00026 #include "amqp_types.h"
00027
00028 #include "assert.h"
00029
00030 #include <iostream>
00031 #include <memory>
00032 #include <vector>
00033
00034 namespace qpid {
00035 namespace framing {
00036
00042 class FieldValueException : public qpid::Exception {};
00043
00049 struct InvalidConversionException : public FieldValueException {
00050 InvalidConversionException() {}
00051 };
00052
00058 class FieldValue {
00059 public:
00060
00061
00062
00063 class Data {
00064 public:
00065 virtual ~Data() {};
00066 virtual uint32_t size() const = 0;
00067 virtual void encode(Buffer& buffer) = 0;
00068 virtual void decode(Buffer& buffer) = 0;
00069 virtual bool operator==(const Data&) const = 0;
00070
00071 virtual bool convertsToInt() const { return false; }
00072 virtual bool convertsToString() const { return false; }
00073 virtual int64_t getInt() const { throw InvalidConversionException();}
00074 virtual std::string getString() const { throw InvalidConversionException(); }
00075
00076 virtual void print(std::ostream& out) const = 0;
00077 };
00078
00079 FieldValue(): data(0) {};
00080
00081 void setType(uint8_t type);
00082 uint8_t getType();
00083 Data& getData() { return *data; }
00084 uint32_t size() const { return 1 + data->size(); };
00085 bool empty() const { return data.get() == 0; }
00086 void encode(Buffer& buffer);
00087 void decode(Buffer& buffer);
00088 bool operator==(const FieldValue&) const;
00089 bool operator!=(const FieldValue& v) const { return !(*this == v); }
00090 void print(std::ostream& out) const { out << "(0x" << std::hex << int(typeOctet) << ")"; data->print(out); }
00091
00092 template <typename T> bool convertsTo() const { return false; }
00093 template <typename T> T get() const { throw InvalidConversionException(); }
00094
00095 protected:
00096 FieldValue(uint8_t t, Data* d): typeOctet(t), data(d) {}
00097
00098 private:
00099 uint8_t typeOctet;
00100 std::auto_ptr<Data> data;
00101 };
00102
00103 template <>
00104 inline bool FieldValue::convertsTo<int>() const { return data->convertsToInt(); }
00105
00106 template <>
00107 inline bool FieldValue::convertsTo<std::string>() const { return data->convertsToString(); }
00108
00109 template <>
00110 inline int FieldValue::get<int>() const { return data->getInt(); }
00111
00112 template <>
00113 inline std::string FieldValue::get<std::string>() const { return data->getString(); }
00114
00115 inline std::ostream& operator<<(std::ostream& out, const FieldValue& v) {
00116 v.print(out);
00117 return out;
00118 }
00119
00120 template <int width>
00121 class FixedWidthValue : public FieldValue::Data {
00122 uint8_t octets[width];
00123
00124 public:
00125 FixedWidthValue() {}
00126 FixedWidthValue(const uint8_t (&data)[width]) : octets(data) {}
00127 FixedWidthValue(uint64_t v)
00128 {
00129 for (int i = width; i > 0; --i) {
00130 octets[i-1] = (uint8_t) (0xFF & v); v >>= 8;
00131 }
00132 octets[0] = (uint8_t) (0xFF & v);
00133 }
00134
00135 uint32_t size() const { return width; }
00136 void encode(Buffer& buffer) { buffer.putRawData(octets, width); }
00137 void decode(Buffer& buffer) { buffer.getRawData(octets, width); }
00138 bool operator==(const Data& d) const {
00139 const FixedWidthValue<width>* rhs = dynamic_cast< const FixedWidthValue<width>* >(&d);
00140 if (rhs == 0) return false;
00141 else return std::equal(&octets[0], &octets[width], &rhs->octets[0]);
00142 }
00143
00144 bool convertsToInt() const { return true; }
00145 int64_t getInt() const
00146 {
00147 int64_t v = 0;
00148 for (int i = 0; i < width-1; ++i) {
00149 v |= octets[i]; v <<= 8;
00150 }
00151 v |= octets[width-1];
00152 return v;
00153 }
00154
00155 void print(std::ostream& o) const { o << "F" << width << ":"; };
00156 };
00157
00158 template <>
00159 class FixedWidthValue<0> : public FieldValue::Data {
00160 public:
00161
00162 uint32_t size() const { return 0; }
00163 void encode(Buffer&) {};
00164 void decode(Buffer&) {};
00165 bool operator==(const Data& d) const {
00166 const FixedWidthValue<0>* rhs = dynamic_cast< const FixedWidthValue<0>* >(&d);
00167 return rhs != 0;
00168 }
00169 void print(std::ostream& o) const { o << "F0"; };
00170 };
00171
00172 template <int lenwidth>
00173 class VariableWidthValue : public FieldValue::Data {
00174 std::vector<uint8_t> octets;
00175
00176 public:
00177 VariableWidthValue() {}
00178 VariableWidthValue(const std::vector<uint8_t>& data) : octets(data) {}
00179 VariableWidthValue(const uint8_t* start, const uint8_t* end) : octets(start, end) {}
00180 uint32_t size() const { return lenwidth + octets.size(); }
00181 void encode(Buffer& buffer) {
00182 buffer.putUInt<lenwidth>(octets.size());
00183 buffer.putRawData(&octets[0], octets.size());
00184 };
00185 void decode(Buffer& buffer) {
00186 uint32_t len = buffer.getUInt<lenwidth>();
00187 octets.resize(len);
00188 buffer.getRawData(&octets[0], len);
00189 }
00190 bool operator==(const Data& d) const {
00191 const VariableWidthValue<lenwidth>* rhs = dynamic_cast< const VariableWidthValue<lenwidth>* >(&d);
00192 if (rhs == 0) return false;
00193 else return octets==rhs->octets;
00194 }
00195
00196 bool convertsToString() const { return true; }
00197 std::string getString() const { return std::string(octets.begin(), octets.end()); }
00198
00199 void print(std::ostream& o) const { o << "V" << lenwidth << ":" << octets.size() << ":"; };
00200 };
00201
00202
00203
00204
00205 class StringValue : public FieldValue {
00206 public:
00207 StringValue(const std::string& v);
00208 };
00209
00210 class Str16Value : public FieldValue {
00211 public:
00212 Str16Value(const std::string& v);
00213 };
00214
00215 class Struct32Value : public FieldValue {
00216 public:
00217 Struct32Value(const std::string& v);
00218 };
00219
00220
00221
00222
00223
00224 class IntegerValue : public FieldValue {
00225 public:
00226 IntegerValue(int v);
00227 };
00228
00229 class TimeValue : public FieldValue {
00230 public:
00231 TimeValue(uint64_t v);
00232 };
00233
00234 class FieldTableValue : public FieldValue {
00235 public:
00236 FieldTableValue(const FieldTable&);
00237 };
00238
00239 }}
00240
00241 #endif