Apache Qpid - AMQP Messaging for Java JMS, C++, Python, Ruby, and .NET Apache Qpid Documentation
qpid/framing/FieldValue.h
Go to the documentation of this file.
00001 #ifndef _framing_FieldValue_h
00002 #define _framing_FieldValue_h
00003 /*
00004  *
00005  * Licensed to the Apache Software Foundation (ASF) under one
00006  * or more contributor license agreements.  See the NOTICE file
00007  * distributed with this work for additional information
00008  * regarding copyright ownership.  The ASF licenses this file
00009  * to you under the Apache License, Version 2.0 (the
00010  * "License"); you may not use this file except in compliance
00011  * with the License.  You may obtain a copy of the License at
00012  *
00013  *   http://www.apache.org/licenses/LICENSE-2.0
00014  *
00015  * Unless required by applicable law or agreed to in writing,
00016  * software distributed under the License is distributed on an
00017  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
00018  * KIND, either express or implied.  See the License for the
00019  * specific language governing permissions and limitations
00020  * under the License.
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      * Abstract type for content of different types
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     // Default assignment operator is fine
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     // Implicit default constructor is fine
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         buffer.checkAvailable(len);
00285         octets.resize(len);
00286         if (len > 0)
00287             buffer.getRawData(&octets[0], len);
00288     }
00289     bool operator==(const Data& d) const {
00290         const VariableWidthValue<lenwidth>* rhs = dynamic_cast< const VariableWidthValue<lenwidth>* >(&d);
00291         if (rhs == 0) return false;
00292         else return octets==rhs->octets;
00293     }
00294 
00295     bool convertsToString() const { return true; }
00296     std::string getString() const { return std::string(octets.begin(), octets.end()); }
00297 
00298     void print(std::ostream& o) const { o << "V" << lenwidth << ":" << octets.size() << ":"; };
00299 };
00300 
00301 template <class T>
00302 class EncodedValue : public FieldValue::Data {
00303     T value;
00304   public:
00305 
00306     EncodedValue() {}
00307     EncodedValue(const T& v) : value(v) {}
00308 
00309     T& getValue() { return value; }
00310     const T& getValue() const { return value; }
00311 
00312     uint32_t encodedSize() const { return value.encodedSize(); }
00313 
00314     void encode(Buffer& buffer) {
00315         value.encode(buffer);
00316     };
00317     void decode(Buffer& buffer) {
00318         value.decode(buffer);
00319     }
00320     bool operator==(const Data& d) const {
00321         const EncodedValue<T>* rhs = dynamic_cast< const EncodedValue<T>* >(&d);
00322         if (rhs == 0) return false;
00323         else return value==rhs->value;
00324     }
00325 
00326     void print(std::ostream& o) const { o << "[" << value << "]"; };
00327 };
00328 
00333 template <class T>
00334 inline bool FieldValue::get(T& t) const
00335 {
00336     const EncodedValue<T>* v = dynamic_cast< EncodedValue<T>* >(data.get());    
00337     if (v != 0) {
00338         t = v->getValue();
00339         return true;
00340     } else {
00341         try {
00342             t = get<T>();
00343             return true;
00344         } catch (const InvalidConversionException&) {
00345             return false;
00346         }
00347     }
00348 }
00349 
00350 class Str8Value : public FieldValue {
00351   public:
00352     QPID_COMMON_EXTERN Str8Value(const std::string& v);
00353 };
00354 
00355 class Str16Value : public FieldValue {
00356   public:
00357     QPID_COMMON_EXTERN Str16Value(const std::string& v);
00358 };
00359 
00360 class Var16Value : public FieldValue {
00361   public:
00362     QPID_COMMON_EXTERN Var16Value(const std::string& v, uint8_t code);
00363 };
00364 
00365 class Var32Value : public FieldValue {
00366   public:
00367     QPID_COMMON_EXTERN Var32Value(const std::string& v, uint8_t code);
00368  };
00369 
00370 class Struct32Value : public FieldValue {
00371   public:
00372     QPID_COMMON_EXTERN Struct32Value(const std::string& v);
00373 };
00374 
00375 class FloatValue : public FieldValue
00376 {
00377   public:
00378     QPID_COMMON_EXTERN FloatValue(float f);
00379 };
00380 class DoubleValue : public FieldValue
00381 {
00382   public:
00383     QPID_COMMON_EXTERN DoubleValue(double f);
00384 };
00385 
00386 /*
00387  * Basic integer value encodes as signed 32 bit
00388  */
00389 class IntegerValue : public FieldValue {
00390   public:
00391     QPID_COMMON_EXTERN IntegerValue(int v);
00392 };
00393 
00394 class TimeValue : public FieldValue {
00395   public:
00396     QPID_COMMON_EXTERN TimeValue(uint64_t v);
00397 };
00398 
00399 class Integer64Value : public FieldValue {
00400   public:
00401     QPID_COMMON_EXTERN Integer64Value(int64_t v);
00402 };
00403 
00404 class Unsigned64Value : public FieldValue {
00405   public:
00406     QPID_COMMON_EXTERN Unsigned64Value(uint64_t v);
00407 };
00408 
00409 class FieldTableValue : public FieldValue {
00410   public:
00411     typedef FieldTable ValueType;
00412     QPID_COMMON_EXTERN FieldTableValue(const FieldTable&);
00413 };
00414 
00415 class ArrayValue : public FieldValue {
00416   public:
00417     QPID_COMMON_EXTERN ArrayValue(const Array&);
00418 };
00419 
00420 class VoidValue : public FieldValue {
00421   public:
00422     QPID_COMMON_EXTERN VoidValue();
00423 };
00424 
00425 class BoolValue : public FieldValue {
00426   public:
00427     QPID_COMMON_EXTERN BoolValue(bool);
00428 };
00429 
00430 class Unsigned8Value : public FieldValue {
00431   public:
00432     QPID_COMMON_EXTERN Unsigned8Value(uint8_t);
00433 };
00434 
00435 class Unsigned16Value : public FieldValue {
00436   public:
00437     QPID_COMMON_EXTERN Unsigned16Value(uint16_t);
00438 };
00439 
00440 class Unsigned32Value : public FieldValue {
00441   public:
00442     QPID_COMMON_EXTERN Unsigned32Value(uint32_t);
00443 };
00444 
00445 class Integer8Value : public FieldValue {
00446   public:
00447     QPID_COMMON_EXTERN Integer8Value(int8_t);
00448 };
00449 
00450 class Integer16Value : public FieldValue {
00451   public:
00452     QPID_COMMON_EXTERN Integer16Value(int16_t);
00453 };
00454 
00455 typedef IntegerValue Integer32Value;
00456 
00457 class ListValue : public FieldValue {
00458   public:
00459     typedef List ValueType;
00460     QPID_COMMON_EXTERN ListValue(const List&);
00461 };
00462 
00463 class UuidValue : public FieldValue {
00464   public:
00465     QPID_COMMON_EXTERN UuidValue();
00466     QPID_COMMON_EXTERN UuidValue(const unsigned char*);
00467 };
00468 
00469 template <class T>
00470 bool getEncodedValue(FieldTable::ValuePtr vptr, T& value)
00471 {
00472     if (vptr) {
00473         const EncodedValue<T>* ev = dynamic_cast< EncodedValue<T>* >(&(vptr->getData()));
00474         if (ev != 0) {
00475             value = ev->getValue();
00476             return true;
00477         }
00478     }
00479     return false;
00480 }
00481 
00482 }} // qpid::framing
00483 
00484 #endif

Qpid C++ API Reference
Generated on Fri Aug 23 2013 for Qpid C++ Client API by doxygen 1.7.5