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 "amqp_types.h"
00026 #include "Buffer.h"
00027 #include "FieldTable.h"
00028 
00029 #include "assert.h"
00030 
00031 #include <iostream>
00032 #include <memory>
00033 #include <vector>
00034 
00035 namespace qpid {
00036 namespace framing {
00037 
00038 //class Array;
00044 class FieldValueException : public qpid::Exception {};
00045 
00051 struct InvalidConversionException : public FieldValueException {
00052     InvalidConversionException() {}
00053 };
00054 
00060 class FieldValue {
00061   public:
00062     /*
00063      * Abstract type for content of different types
00064      */
00065     class Data {
00066       public:
00067         virtual ~Data() {};
00068         virtual uint32_t encodedSize() const = 0;        
00069         virtual void encode(Buffer& buffer) = 0;
00070         virtual void decode(Buffer& buffer) = 0;
00071         virtual bool operator==(const Data&) const = 0;
00072 
00073         virtual bool convertsToInt() const { return false; }
00074         virtual bool convertsToString() const { return false; }
00075         virtual int64_t getInt() const { throw InvalidConversionException();}
00076         virtual std::string getString() const { throw InvalidConversionException(); }
00077 
00078         virtual void print(std::ostream& out) const = 0;
00079     };
00080 
00081     FieldValue(): data(0) {};
00082     // Default assignment operator is fine
00083     void setType(uint8_t type);
00084     uint8_t getType();
00085     Data& getData() { return *data; }
00086     uint32_t encodedSize() const { return 1 + data->encodedSize(); };
00087     bool empty() const { return data.get() == 0; } 
00088     void encode(Buffer& buffer);
00089     void decode(Buffer& buffer);
00090     bool operator==(const FieldValue&) const;
00091     bool operator!=(const FieldValue& v) const { return !(*this == v); }
00092     
00093     void print(std::ostream& out) const;
00094     
00095     template <typename T> bool convertsTo() const { return false; }
00096     template <typename T> T get() const { throw InvalidConversionException(); }
00097 
00098   protected:
00099     FieldValue(uint8_t t, Data* d): typeOctet(t), data(d) {}
00100 
00101   private:
00102     uint8_t typeOctet;
00103     std::auto_ptr<Data> data; 
00104 };
00105 
00106 template <>
00107 inline bool FieldValue::convertsTo<int>() const { return data->convertsToInt(); }
00108 
00109 template <>
00110 inline bool FieldValue::convertsTo<int64_t>() const { return data->convertsToInt(); }
00111 
00112 template <>
00113 inline bool FieldValue::convertsTo<std::string>() const { return data->convertsToString(); }
00114 
00115 template <>
00116 inline int FieldValue::get<int>() const { return data->getInt(); }
00117 
00118 template <>
00119 inline int64_t FieldValue::get<int64_t>() const { return data->getInt(); }
00120 
00121 template <>
00122 inline std::string FieldValue::get<std::string>() const { return data->getString(); }
00123 
00124 inline std::ostream& operator<<(std::ostream& out, const FieldValue& v) {
00125     v.print(out);
00126     return out;
00127 }
00128 
00129 template <int width>
00130 class FixedWidthValue : public FieldValue::Data {
00131     uint8_t octets[width];
00132     
00133   public:
00134     FixedWidthValue() {}
00135     FixedWidthValue(const uint8_t (&data)[width]) : octets(data) {}
00136     FixedWidthValue(const uint8_t* const data)
00137     {
00138         for (int i = 0; i < width; i++) octets[i] = data[i];
00139     }
00140     FixedWidthValue(uint64_t v)
00141     {
00142         for (int i = width; i > 1; --i) {
00143             octets[i-1] = (uint8_t) (0xFF & v); v >>= 8;
00144         }
00145         octets[0] = (uint8_t) (0xFF & v);
00146     }
00147     uint32_t encodedSize() const { return width; }
00148     void encode(Buffer& buffer) { buffer.putRawData(octets, width); }
00149     void decode(Buffer& buffer) { buffer.getRawData(octets, width); }
00150     bool operator==(const Data& d) const {
00151         const FixedWidthValue<width>* rhs = dynamic_cast< const FixedWidthValue<width>* >(&d);
00152         if (rhs == 0) return false;
00153         else return std::equal(&octets[0], &octets[width], &rhs->octets[0]); 
00154     }
00155 
00156     bool convertsToInt() const { return true; }
00157     int64_t getInt() const
00158     {
00159         int64_t v = 0;
00160         for (int i = 0; i < width-1; ++i) {
00161             v |= octets[i]; v <<= 8;
00162         }
00163         v |= octets[width-1];
00164         return v;
00165     }
00166     uint8_t* rawOctets() { return octets; }
00167 
00168     void print(std::ostream& o) const { o << "F" << width << ":"; };
00169 };
00170 
00171 template <>
00172 class FixedWidthValue<0> : public FieldValue::Data {
00173   public:
00174     // Implicit default constructor is fine
00175     uint32_t encodedSize() const { return 0; }
00176     void encode(Buffer&) {};
00177     void decode(Buffer&) {};
00178     bool operator==(const Data& d) const {
00179         const FixedWidthValue<0>* rhs = dynamic_cast< const FixedWidthValue<0>* >(&d);
00180         return rhs != 0;
00181     }
00182     void print(std::ostream& o) const { o << "F0"; };
00183 };
00184 
00185 template <int lenwidth>
00186 class VariableWidthValue : public FieldValue::Data {
00187     std::vector<uint8_t> octets;
00188 
00189   public:
00190     VariableWidthValue() {}
00191     VariableWidthValue(const std::vector<uint8_t>& data) : octets(data) {}
00192     VariableWidthValue(const uint8_t* start, const uint8_t* end) : octets(start, end) {}
00193     uint32_t encodedSize() const { return lenwidth + octets.size(); } 
00194     void encode(Buffer& buffer) {
00195         buffer.putUInt<lenwidth>(octets.size());
00196         if (octets.size() > 0)
00197             buffer.putRawData(&octets[0], octets.size());
00198     };
00199     void decode(Buffer& buffer) {
00200         uint32_t len = buffer.getUInt<lenwidth>();
00201         octets.resize(len);
00202         if (len > 0)
00203             buffer.getRawData(&octets[0], len);
00204     }
00205     bool operator==(const Data& d) const {
00206         const VariableWidthValue<lenwidth>* rhs = dynamic_cast< const VariableWidthValue<lenwidth>* >(&d);
00207         if (rhs == 0) return false;
00208         else return octets==rhs->octets; 
00209     }
00210     
00211     bool convertsToString() const { return true; }
00212     std::string getString() const { return std::string(octets.begin(), octets.end()); }
00213 
00214     void print(std::ostream& o) const { o << "V" << lenwidth << ":" << octets.size() << ":"; };
00215 };
00216 
00217 template <class T> 
00218 class EncodedValue : public FieldValue::Data {
00219     T value;
00220   public:
00221 
00222     EncodedValue() {}
00223     EncodedValue(const T& v) : value(v) {}
00224 
00225     T& getValue() { return value; }
00226     const T& getValue() const { return value; }
00227 
00228     uint32_t encodedSize() const { return value.encodedSize(); } 
00229 
00230     void encode(Buffer& buffer) {
00231         value.encode(buffer);
00232     };
00233     void decode(Buffer& buffer) {
00234         value.decode(buffer);
00235     }
00236     bool operator==(const Data& d) const {
00237         const EncodedValue<T>* rhs = dynamic_cast< const EncodedValue<T>* >(&d);
00238         if (rhs == 0) return false;
00239         else return value==rhs->value; 
00240     }
00241 
00242     void print(std::ostream& o) const { o << "[" << value << "]"; };
00243 };
00244 
00245 class Str8Value : public FieldValue {
00246   public:
00247     Str8Value(const std::string& v);
00248 };
00249 
00250 class Str16Value : public FieldValue {
00251   public:
00252     Str16Value(const std::string& v);
00253 };
00254 
00255 class Struct32Value : public FieldValue {
00256   public:
00257     Struct32Value(const std::string& v);
00258 };
00259 
00260 class FloatValue : public FieldValue
00261 {
00262   public:
00263     FloatValue(float f);
00264 };
00265 class DoubleValue : public FieldValue
00266 {
00267   public:
00268     DoubleValue(double f);
00269 };
00270 
00271 /*
00272  * Basic integer value encodes as signed 32 bit
00273  */
00274 class IntegerValue : public FieldValue {
00275   public:
00276     IntegerValue(int v);
00277 };
00278 
00279 class TimeValue : public FieldValue {
00280   public:
00281     TimeValue(uint64_t v);
00282 };
00283 
00284 class Integer64Value : public FieldValue {
00285   public:
00286     Integer64Value(int64_t v);
00287 };
00288 
00289 class Unsigned64Value : public FieldValue {
00290   public:
00291     Unsigned64Value(uint64_t v);
00292 };
00293 
00294 class FieldTableValue : public FieldValue {
00295   public:
00296     FieldTableValue(const FieldTable&);
00297 };
00298 
00299 class ArrayValue : public FieldValue {
00300   public:
00301     ArrayValue(const Array&);
00302 };
00303 
00304 template <class T>
00305 bool getEncodedValue(FieldTable::ValuePtr vptr, T& value) 
00306 {
00307     if (vptr) {
00308         const EncodedValue<T>* ev = dynamic_cast< EncodedValue<T>* >(&(vptr->getData()));    
00309         if (ev != 0) {
00310             value = ev->getValue(); 
00311             return true;
00312         }
00313     }
00314     return false;
00315 }
00316 
00317 
00318 }} // qpid::framing
00319 
00320 #endif

Qpid C++ API Reference
Generated on Tue Dec 8 15:39:48 2009 for Qpid C++ Client API by doxygen 1.4.7