Go to the documentation of this file.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 "qpid/framing/amqp_types.h"
00026 #include "qpid/framing/Buffer.h"
00027 #include "qpid/framing/FieldTable.h"
00028 #include "qpid/CommonImportExport.h"
00029
00030 #include <iostream>
00031 #include <memory>
00032 #include <vector>
00033
00034 #include <assert.h>
00035
00036 namespace qpid {
00037 namespace framing {
00038
00044 class FieldValueException : public qpid::Exception {};
00045
00051 struct InvalidConversionException : public FieldValueException {
00052 InvalidConversionException() {}
00053 };
00054
00055 class List;
00056
00062 class FieldValue {
00063 public:
00064
00065
00066
00067 class Data {
00068 public:
00069 virtual ~Data() {};
00070 virtual uint32_t encodedSize() const = 0;
00071 virtual void encode(Buffer& buffer) = 0;
00072 virtual void decode(Buffer& buffer) = 0;
00073 virtual bool operator==(const Data&) const = 0;
00074
00075 virtual bool convertsToInt() const { return false; }
00076 virtual bool convertsToString() const { return false; }
00077 virtual int64_t getInt() const { throw InvalidConversionException();}
00078 virtual std::string getString() const { throw InvalidConversionException(); }
00079
00080 virtual void print(std::ostream& out) const = 0;
00081 };
00082
00083 FieldValue(): data(0) {};
00084
00085 void setType(uint8_t type);
00086 QPID_COMMON_EXTERN uint8_t getType() const;
00087 Data& getData() { return *data; }
00088 uint32_t encodedSize() const { return 1 + data->encodedSize(); };
00089 bool empty() const { return data.get() == 0; }
00090 void encode(Buffer& buffer);
00091 void decode(Buffer& buffer);
00092 QPID_COMMON_EXTERN bool operator==(const FieldValue&) const;
00093 QPID_COMMON_EXTERN bool operator!=(const FieldValue& v) const { return !(*this == v); }
00094
00095 QPID_COMMON_EXTERN void print(std::ostream& out) const;
00096
00097 template <typename T> bool convertsTo() const { return false; }
00098 template <typename T> T get() const { throw InvalidConversionException(); }
00099
00100 template <class T, int W> T getIntegerValue() const;
00101 template <class T, int W> T getFloatingPointValue() const;
00102 template <int W> void getFixedWidthValue(unsigned char*) const;
00103 template <class T> bool get(T&) const;
00104
00105 protected:
00106 FieldValue(uint8_t t, Data* d): typeOctet(t), data(d) {}
00107
00108 QPID_COMMON_EXTERN static uint8_t* convertIfRequired(uint8_t* const octets, int width);
00109
00110 private:
00111 uint8_t typeOctet;
00112 std::auto_ptr<Data> data;
00113
00114 };
00115
00116 template <>
00117 inline bool FieldValue::convertsTo<int>() const { return data->convertsToInt(); }
00118
00119 template <>
00120 inline bool FieldValue::convertsTo<int64_t>() const { return data->convertsToInt(); }
00121
00122 template <>
00123 inline bool FieldValue::convertsTo<std::string>() const { return data->convertsToString(); }
00124
00125 template <>
00126 inline int FieldValue::get<int>() const { return static_cast<int>(data->getInt()); }
00127
00128 template <>
00129 inline int64_t FieldValue::get<int64_t>() const { return data->getInt(); }
00130
00131 template <>
00132 inline std::string FieldValue::get<std::string>() const { return data->getString(); }
00133
00134 inline std::ostream& operator<<(std::ostream& out, const FieldValue& v) {
00135 v.print(out);
00136 return out;
00137 }
00138
00139 template <int width>
00140 class FixedWidthValue : public FieldValue::Data {
00141 uint8_t octets[width];
00142
00143 public:
00144 FixedWidthValue() {}
00145 FixedWidthValue(const uint8_t (&data)[width]) : octets(data) {}
00146 FixedWidthValue(const uint8_t* const data)
00147 {
00148 for (int i = 0; i < width; i++) octets[i] = data[i];
00149 }
00150 FixedWidthValue(uint64_t v)
00151 {
00152 for (int i = width; i > 1; --i) {
00153 octets[i-1] = (uint8_t) (0xFF & v); v >>= 8;
00154 }
00155 octets[0] = (uint8_t) (0xFF & v);
00156 }
00157 uint32_t encodedSize() const { return width; }
00158 void encode(Buffer& buffer) { buffer.putRawData(octets, width); }
00159 void decode(Buffer& buffer) { buffer.getRawData(octets, width); }
00160 bool operator==(const Data& d) const {
00161 const FixedWidthValue<width>* rhs = dynamic_cast< const FixedWidthValue<width>* >(&d);
00162 if (rhs == 0) return false;
00163 else return std::equal(&octets[0], &octets[width], &rhs->octets[0]);
00164 }
00165
00166 bool convertsToInt() const { return true; }
00167 int64_t getInt() const
00168 {
00169 int64_t v = 0;
00170 for (int i = 0; i < width-1; ++i) {
00171 v |= octets[i]; v <<= 8;
00172 }
00173 v |= octets[width-1];
00174 return v;
00175 }
00176 uint8_t* rawOctets() { return octets; }
00177 uint8_t* rawOctets() const { return octets; }
00178
00179 void print(std::ostream& o) const { o << "F" << width << ":"; };
00180 };
00181
00182 template <class T, int W>
00183 inline T FieldValue::getIntegerValue() const
00184 {
00185 FixedWidthValue<W>* const fwv = dynamic_cast< FixedWidthValue<W>* const>(data.get());
00186 if (fwv) {
00187 uint8_t* octets = fwv->rawOctets();
00188 T v = 0;
00189 for (int i = 0; i < W-1; ++i) {
00190 v |= octets[i]; v <<= 8;
00191 }
00192 v |= octets[W-1];
00193 return v;
00194 } else {
00195 throw InvalidConversionException();
00196 }
00197 }
00198
00199 template <class T, int W>
00200 inline T FieldValue::getFloatingPointValue() const {
00201 FixedWidthValue<W>* const fwv = dynamic_cast< FixedWidthValue<W>* const>(data.get());
00202 if (fwv) {
00203 T value;
00204 uint8_t* const octets = convertIfRequired(fwv->rawOctets(), W);
00205 uint8_t* const target = reinterpret_cast<uint8_t*>(&value);
00206 for (size_t i = 0; i < W; ++i) target[i] = octets[i];
00207 return value;
00208 } else {
00209 throw InvalidConversionException();
00210 }
00211 }
00212
00213 template <int W> void FieldValue::getFixedWidthValue(unsigned char* value) const
00214 {
00215 FixedWidthValue<W>* const fwv = dynamic_cast< FixedWidthValue<W>* const>(data.get());
00216 if (fwv) {
00217 for (size_t i = 0; i < W; ++i) value[i] = fwv->rawOctets()[i];
00218 } else {
00219 throw InvalidConversionException();
00220 }
00221 }
00222
00223 template <>
00224 inline float FieldValue::get<float>() const {
00225 return getFloatingPointValue<float, 4>();
00226 }
00227
00228 template <>
00229 inline double FieldValue::get<double>() const {
00230 return getFloatingPointValue<double, 8>();
00231 }
00232
00233 template <>
00234 class FixedWidthValue<0> : public FieldValue::Data {
00235 public:
00236
00237 uint32_t encodedSize() const { return 0; }
00238 void encode(Buffer&) {};
00239 void decode(Buffer&) {};
00240 bool operator==(const Data& d) const {
00241 const FixedWidthValue<0>* rhs = dynamic_cast< const FixedWidthValue<0>* >(&d);
00242 return rhs != 0;
00243 }
00244 void print(std::ostream& o) const { o << "F0"; };
00245 };
00246
00247 template <int lenwidth>
00248 class VariableWidthValue : public FieldValue::Data {
00249 std::vector<uint8_t> octets;
00250
00251 public:
00252 VariableWidthValue() {}
00253 VariableWidthValue(const std::vector<uint8_t>& data) : octets(data) {}
00254 VariableWidthValue(const uint8_t* start, const uint8_t* end) : octets(start, end) {}
00255 uint32_t encodedSize() const { return lenwidth + octets.size(); }
00256 void encode(Buffer& buffer) {
00257 buffer.putUInt<lenwidth>(octets.size());
00258 if (octets.size() > 0)
00259 buffer.putRawData(&octets[0], octets.size());
00260 };
00261 void decode(Buffer& buffer) {
00262 uint32_t len = buffer.getUInt<lenwidth>();
00263 octets.resize(len);
00264 if (len > 0)
00265 buffer.getRawData(&octets[0], len);
00266 }
00267 bool operator==(const Data& d) const {
00268 const VariableWidthValue<lenwidth>* rhs = dynamic_cast< const VariableWidthValue<lenwidth>* >(&d);
00269 if (rhs == 0) return false;
00270 else return octets==rhs->octets;
00271 }
00272
00273 bool convertsToString() const { return true; }
00274 std::string getString() const { return std::string(octets.begin(), octets.end()); }
00275
00276 void print(std::ostream& o) const { o << "V" << lenwidth << ":" << octets.size() << ":"; };
00277 };
00278
00279 template <class T>
00280 class EncodedValue : public FieldValue::Data {
00281 T value;
00282 public:
00283
00284 EncodedValue() {}
00285 EncodedValue(const T& v) : value(v) {}
00286
00287 T& getValue() { return value; }
00288 const T& getValue() const { return value; }
00289
00290 uint32_t encodedSize() const { return value.encodedSize(); }
00291
00292 void encode(Buffer& buffer) {
00293 value.encode(buffer);
00294 };
00295 void decode(Buffer& buffer) {
00296 value.decode(buffer);
00297 }
00298 bool operator==(const Data& d) const {
00299 const EncodedValue<T>* rhs = dynamic_cast< const EncodedValue<T>* >(&d);
00300 if (rhs == 0) return false;
00301 else return value==rhs->value;
00302 }
00303
00304 void print(std::ostream& o) const { o << "[" << value << "]"; };
00305 };
00306
00311 template <class T>
00312 inline bool FieldValue::get(T& t) const
00313 {
00314 const EncodedValue<T>* v = dynamic_cast< EncodedValue<T>* >(data.get());
00315 if (v != 0) {
00316 t = v->getValue();
00317 return true;
00318 } else {
00319 try {
00320 t = get<T>();
00321 return true;
00322 } catch (const InvalidConversionException&) {
00323 return false;
00324 }
00325 }
00326 }
00327
00328 class Str8Value : public FieldValue {
00329 public:
00330 QPID_COMMON_EXTERN Str8Value(const std::string& v);
00331 };
00332
00333 class Str16Value : public FieldValue {
00334 public:
00335 QPID_COMMON_EXTERN Str16Value(const std::string& v);
00336 };
00337
00338 class Var16Value : public FieldValue {
00339 public:
00340 QPID_COMMON_EXTERN Var16Value(const std::string& v, uint8_t code);
00341 };
00342
00343 class Var32Value : public FieldValue {
00344 public:
00345 QPID_COMMON_EXTERN Var32Value(const std::string& v, uint8_t code);
00346 };
00347
00348 class Struct32Value : public FieldValue {
00349 public:
00350 QPID_COMMON_EXTERN Struct32Value(const std::string& v);
00351 };
00352
00353 class FloatValue : public FieldValue
00354 {
00355 public:
00356 QPID_COMMON_EXTERN FloatValue(float f);
00357 };
00358 class DoubleValue : public FieldValue
00359 {
00360 public:
00361 QPID_COMMON_EXTERN DoubleValue(double f);
00362 };
00363
00364
00365
00366
00367 class IntegerValue : public FieldValue {
00368 public:
00369 QPID_COMMON_EXTERN IntegerValue(int v);
00370 };
00371
00372 class TimeValue : public FieldValue {
00373 public:
00374 QPID_COMMON_EXTERN TimeValue(uint64_t v);
00375 };
00376
00377 class Integer64Value : public FieldValue {
00378 public:
00379 QPID_COMMON_EXTERN Integer64Value(int64_t v);
00380 };
00381
00382 class Unsigned64Value : public FieldValue {
00383 public:
00384 QPID_COMMON_EXTERN Unsigned64Value(uint64_t v);
00385 };
00386
00387 class FieldTableValue : public FieldValue {
00388 public:
00389 typedef FieldTable ValueType;
00390 QPID_COMMON_EXTERN FieldTableValue(const FieldTable&);
00391 };
00392
00393 class ArrayValue : public FieldValue {
00394 public:
00395 QPID_COMMON_EXTERN ArrayValue(const Array&);
00396 };
00397
00398 class VoidValue : public FieldValue {
00399 public:
00400 QPID_COMMON_EXTERN VoidValue();
00401 };
00402
00403 class BoolValue : public FieldValue {
00404 public:
00405 QPID_COMMON_EXTERN BoolValue(bool);
00406 };
00407
00408 class Unsigned8Value : public FieldValue {
00409 public:
00410 QPID_COMMON_EXTERN Unsigned8Value(uint8_t);
00411 };
00412
00413 class Unsigned16Value : public FieldValue {
00414 public:
00415 QPID_COMMON_EXTERN Unsigned16Value(uint16_t);
00416 };
00417
00418 class Unsigned32Value : public FieldValue {
00419 public:
00420 QPID_COMMON_EXTERN Unsigned32Value(uint32_t);
00421 };
00422
00423 class Integer8Value : public FieldValue {
00424 public:
00425 QPID_COMMON_EXTERN Integer8Value(int8_t);
00426 };
00427
00428 class Integer16Value : public FieldValue {
00429 public:
00430 QPID_COMMON_EXTERN Integer16Value(int16_t);
00431 };
00432
00433 typedef IntegerValue Integer32Value;
00434
00435 class ListValue : public FieldValue {
00436 public:
00437 typedef List ValueType;
00438 QPID_COMMON_EXTERN ListValue(const List&);
00439 };
00440
00441 class UuidValue : public FieldValue {
00442 public:
00443 QPID_COMMON_EXTERN UuidValue(const unsigned char*);
00444 };
00445
00446 template <class T>
00447 bool getEncodedValue(FieldTable::ValuePtr vptr, T& value)
00448 {
00449 if (vptr) {
00450 const EncodedValue<T>* ev = dynamic_cast< EncodedValue<T>* >(&(vptr->getData()));
00451 if (ev != 0) {
00452 value = ev->getValue();
00453 return true;
00454 }
00455 }
00456 return false;
00457 }
00458
00459 }}
00460
00461 #endif