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