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