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 "amqp_types.h"
00026 #include "Buffer.h"
00027 #include "FieldTable.h"
00028
00029 #include "assert.h"
00030
00031 #include <iostream>
00032 #include <memory>
00033 #include <vector>
00034
00035 namespace qpid {
00036 namespace framing {
00037
00038
00044 class FieldValueException : public qpid::Exception {};
00045
00051 struct InvalidConversionException : public FieldValueException {
00052 InvalidConversionException() {}
00053 };
00054
00060 class FieldValue {
00061 public:
00062
00063
00064
00065 class Data {
00066 public:
00067 virtual ~Data() {};
00068 virtual uint32_t encodedSize() const = 0;
00069 virtual void encode(Buffer& buffer) = 0;
00070 virtual void decode(Buffer& buffer) = 0;
00071 virtual bool operator==(const Data&) const = 0;
00072
00073 virtual bool convertsToInt() const { return false; }
00074 virtual bool convertsToString() const { return false; }
00075 virtual int64_t getInt() const { throw InvalidConversionException();}
00076 virtual std::string getString() const { throw InvalidConversionException(); }
00077
00078 virtual void print(std::ostream& out) const = 0;
00079 };
00080
00081 FieldValue(): data(0) {};
00082
00083 void setType(uint8_t type);
00084 uint8_t getType();
00085 Data& getData() { return *data; }
00086 uint32_t encodedSize() const { return 1 + data->encodedSize(); };
00087 bool empty() const { return data.get() == 0; }
00088 void encode(Buffer& buffer);
00089 void decode(Buffer& buffer);
00090 bool operator==(const FieldValue&) const;
00091 bool operator!=(const FieldValue& v) const { return !(*this == v); }
00092 void print(std::ostream& out) const { out << "(0x" << std::hex << int(typeOctet) << ")"; data->print(out); }
00093
00094 template <typename T> bool convertsTo() const { return false; }
00095 template <typename T> T get() const { throw InvalidConversionException(); }
00096
00097 protected:
00098 FieldValue(uint8_t t, Data* d): typeOctet(t), data(d) {}
00099
00100 private:
00101 uint8_t typeOctet;
00102 std::auto_ptr<Data> data;
00103 };
00104
00105 template <>
00106 inline bool FieldValue::convertsTo<int>() const { return data->convertsToInt(); }
00107
00108 template <>
00109 inline bool FieldValue::convertsTo<int64_t>() const { return data->convertsToInt(); }
00110
00111 template <>
00112 inline bool FieldValue::convertsTo<std::string>() const { return data->convertsToString(); }
00113
00114 template <>
00115 inline int FieldValue::get<int>() const { return data->getInt(); }
00116
00117 template <>
00118 inline int64_t FieldValue::get<int64_t>() const { return data->getInt(); }
00119
00120 template <>
00121 inline std::string FieldValue::get<std::string>() const { return data->getString(); }
00122
00123 inline std::ostream& operator<<(std::ostream& out, const FieldValue& v) {
00124 v.print(out);
00125 return out;
00126 }
00127
00128 template <int width>
00129 class FixedWidthValue : public FieldValue::Data {
00130 uint8_t octets[width];
00131
00132 public:
00133 FixedWidthValue() {}
00134 FixedWidthValue(const uint8_t (&data)[width]) : octets(data) {}
00135 FixedWidthValue(const uint8_t* const data)
00136 {
00137 for (int i = 0; i < width; i++) octets[i] = data[i];
00138 }
00139 FixedWidthValue(uint64_t v)
00140 {
00141 for (int i = width; i > 0; --i) {
00142 octets[i-1] = (uint8_t) (0xFF & v); v >>= 8;
00143 }
00144 octets[0] = (uint8_t) (0xFF & v);
00145 }
00146 uint32_t encodedSize() const { return width; }
00147 void encode(Buffer& buffer) { buffer.putRawData(octets, width); }
00148 void decode(Buffer& buffer) { buffer.getRawData(octets, width); }
00149 bool operator==(const Data& d) const {
00150 const FixedWidthValue<width>* rhs = dynamic_cast< const FixedWidthValue<width>* >(&d);
00151 if (rhs == 0) return false;
00152 else return std::equal(&octets[0], &octets[width], &rhs->octets[0]);
00153 }
00154
00155 bool convertsToInt() const { return true; }
00156 int64_t getInt() const
00157 {
00158 int64_t v = 0;
00159 for (int i = 0; i < width-1; ++i) {
00160 v |= octets[i]; v <<= 8;
00161 }
00162 v |= octets[width-1];
00163 return v;
00164 }
00165 void copyInto(uint8_t* const data) const
00166 {
00167 for (uint i = 0; i < width; ++i) data[i] = octets[i];
00168 }
00169
00170 void print(std::ostream& o) const { o << "F" << width << ":"; };
00171 };
00172
00173 template <>
00174 class FixedWidthValue<0> : public FieldValue::Data {
00175 public:
00176
00177 uint32_t encodedSize() const { return 0; }
00178 void encode(Buffer&) {};
00179 void decode(Buffer&) {};
00180 bool operator==(const Data& d) const {
00181 const FixedWidthValue<0>* rhs = dynamic_cast< const FixedWidthValue<0>* >(&d);
00182 return rhs != 0;
00183 }
00184 void print(std::ostream& o) const { o << "F0"; };
00185 };
00186
00187 template <int lenwidth>
00188 class VariableWidthValue : public FieldValue::Data {
00189 std::vector<uint8_t> octets;
00190
00191 public:
00192 VariableWidthValue() {}
00193 VariableWidthValue(const std::vector<uint8_t>& data) : octets(data) {}
00194 VariableWidthValue(const uint8_t* start, const uint8_t* end) : octets(start, end) {}
00195 uint32_t encodedSize() const { return lenwidth + octets.size(); }
00196 void encode(Buffer& buffer) {
00197 buffer.putUInt<lenwidth>(octets.size());
00198 buffer.putRawData(&octets[0], octets.size());
00199 };
00200 void decode(Buffer& buffer) {
00201 uint32_t len = buffer.getUInt<lenwidth>();
00202 octets.resize(len);
00203 buffer.getRawData(&octets[0], len);
00204 }
00205 bool operator==(const Data& d) const {
00206 const VariableWidthValue<lenwidth>* rhs = dynamic_cast< const VariableWidthValue<lenwidth>* >(&d);
00207 if (rhs == 0) return false;
00208 else return octets==rhs->octets;
00209 }
00210
00211 bool convertsToString() const { return true; }
00212 std::string getString() const { return std::string(octets.begin(), octets.end()); }
00213
00214 void print(std::ostream& o) const { o << "V" << lenwidth << ":" << octets.size() << ":"; };
00215 };
00216
00217 template <class T>
00218 class EncodedValue : public FieldValue::Data {
00219 T value;
00220 public:
00221
00222 EncodedValue() {}
00223 EncodedValue(const T& v) : value(v) {}
00224
00225 T& getValue() { return value; }
00226 const T& getValue() const { return value; }
00227
00228 uint32_t encodedSize() const { return value.encodedSize(); }
00229
00230 void encode(Buffer& buffer) {
00231 value.encode(buffer);
00232 };
00233 void decode(Buffer& buffer) {
00234 value.decode(buffer);
00235 }
00236 bool operator==(const Data& d) const {
00237 const EncodedValue<T>* rhs = dynamic_cast< const EncodedValue<T>* >(&d);
00238 if (rhs == 0) return false;
00239 else return value==rhs->value;
00240 }
00241
00242 void print(std::ostream& o) const { o << "[" << value << "]"; };
00243 };
00244
00245
00246
00247
00248 class StringValue : public FieldValue {
00249 public:
00250 StringValue(const std::string& v);
00251 };
00252
00253 class Str16Value : public FieldValue {
00254 public:
00255 Str16Value(const std::string& v);
00256 };
00257
00258 class Struct32Value : public FieldValue {
00259 public:
00260 Struct32Value(const std::string& v);
00261 };
00262
00263 class FloatValue : public FieldValue
00264 {
00265 public:
00266 FloatValue(float f);
00267 };
00268 class DoubleValue : public FieldValue
00269 {
00270 public:
00271 DoubleValue(double f);
00272 };
00273
00274
00275
00276
00277 class IntegerValue : public FieldValue {
00278 public:
00279 IntegerValue(int v);
00280 };
00281
00282 class TimeValue : public FieldValue {
00283 public:
00284 TimeValue(uint64_t v);
00285 };
00286
00287 class Integer64Value : public FieldValue {
00288 public:
00289 Integer64Value(int64_t v);
00290 };
00291
00292 class Unsigned64Value : public FieldValue {
00293 public:
00294 Unsigned64Value(uint64_t v);
00295 };
00296
00297 class FieldTableValue : public FieldValue {
00298 public:
00299 FieldTableValue(const FieldTable&);
00300 };
00301
00302 class ArrayValue : public FieldValue {
00303 public:
00304 ArrayValue(const Array&);
00305 };
00306
00307
00308 template <class T>
00309 bool getEncodedValue(FieldTable::ValuePtr vptr, T& value)
00310 {
00311 if (vptr) {
00312 const EncodedValue<T>* ev = dynamic_cast< EncodedValue<T>* >(&(vptr->getData()));
00313 if (ev != 0) {
00314 value = ev->getValue();
00315 return true;
00316 }
00317 }
00318 return false;
00319 }
00320
00321
00322 }}
00323
00324 #endif