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