Apache Qpid C++ API
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 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      * 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_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     // Implicit default constructor is fine
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  * Basic integer value encodes as signed 32 bit
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 }} // qpid::framing
00460 
00461 #endif

Qpid C++ API Reference
Generated on Wed Feb 8 13:31:05 2012 for Qpid C++ Client API by doxygen 1.4.7