/usr/share/cruisecontrol-bin-2.6.1/projects/qpid-trunk/cpp/src/qpid/amqp_0_10/Map.h

00001 #ifndef QPID_AMQP_0_10_MAP_H
00002 #define QPID_AMQP_0_10_MAP_H
00003 
00004 /*
00005  *
00006  * Licensed to the Apache Software Foundation (ASF) under one
00007  * or more contributor license agreements.  See the NOTICE file
00008  * distributed with this work for additional information
00009  * regarding copyright ownership.  The ASF licenses this file
00010  * to you under the Apache License, Version 2.0 (the
00011  * "License"); you may not use this file except in compliance
00012  * with the License.  You may obtain a copy of the License at
00013  * 
00014  *   http://www.apache.org/licenses/LICENSE-2.0
00015  * 
00016  * Unless required by applicable law or agreed to in writing,
00017  * software distributed under the License is distributed on ang
00018  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
00019  * KIND, either express or implied.  See the License for the
00020  * specific language governing permissions and limitations
00021  * under the License.
00022  *
00023  */
00024 
00025 #include "qpid/Exception.h"
00026 #include "qpid/amqp_0_10/built_in_types.h"
00027 #include "qpid/amqp_0_10/UnknownType.h"
00028 #include "qpid/amqp_0_10/CodeForType.h"
00029 #include "qpid/amqp_0_10/TypeForCode.h"
00030 #include "qpid/amqp_0_10/Codec.h"
00031 #include "qpid/framing/Blob.h"
00032 #include <map>
00033 #include <string>
00034 #include <iosfwd>
00035 
00036 namespace qpid {
00037 namespace amqp_0_10 {
00038 
00039 class Map;
00040 
00041 class MapValue {
00042   public:
00043     struct BadTypeException : public Exception {};
00044 
00045     template <class R> struct Visitor { typedef R result_type; };
00046 
00047     MapValue();
00048     MapValue(const MapValue& x);
00049     template <class T> explicit MapValue(const T& t);
00050     template <class T> MapValue& operator=(const T& t);
00051 
00052     template <class T> T* get();
00053     template <class T> const T* get() const;
00054 
00055     template <class V> typename V::result_type apply_visitor(V&);
00056     template <class V> typename V::result_type apply_visitor(const V&);
00057 
00058     uint8_t getCode() const { return code; }
00059     
00060     bool operator==(const MapValue&) const;
00061 
00062     template <class S> void serialize(S& s) { s(code); s.split(*this); }
00063     template <class S> void encode(S& s) const {
00064         const_cast<MapValue*>(this)->apply_visitor(s);
00065     }
00066     template <class S> void decode(S& s) {
00067         DecodeVisitor<S> dv(blob, s);
00068         qpid::amqp_0_10::apply_visitor(dv, code);
00069     }
00070     
00071 
00072   private:
00073     static const size_t SIZE=128 < sizeof(Vbin32) ? sizeof(Vbin32) : 128;
00074     typedef framing::Blob<SIZE> Blob;
00075 
00076     template <class V> struct VisitVisitor;
00077     template <class T> struct GetVisitor;
00078     template <class D> struct DecodeVisitor;
00079 
00080     uint8_t code;
00081     Blob blob;
00082 };
00083 
00084 class Map : public std::map<Str8, MapValue> {
00085   public:
00086     template <class S> void serialize(S& s) { s.split(*this); }
00087     template <class S> void encode(S& s) const;
00088     // Shortcut calculation for size.
00089     void encode(Codec::Size& s) const  { s.raw(0, contentSize() + 4/*size*/); }
00090 
00091     template <class S> void decode(S& s);
00092     
00093   private:
00094     uint32_t contentSize() const;
00095 };
00096 
00097 std::ostream& operator<<(std::ostream&, const MapValue&);
00098 std::ostream& operator<<(std::ostream&, const Map::value_type&);
00099 std::ostream& operator<<(std::ostream&, const Map&);
00100 
00101 using framing::in_place;
00102 
00103 template <class T> MapValue::MapValue(const T& t) : code(codeFor(t)), blob(in_place<t>()) {}
00104 
00105 template <class T> MapValue& MapValue::operator=(const T& t) {
00106     code=codeFor(t);
00107     blob=t;
00108     return *this;
00109 }
00110 
00111 template <class V> struct MapValue::VisitVisitor {
00112     typedef typename V::result_type result_type;
00113     V& visitor;
00114     Blob& blob;
00115     VisitVisitor(V& v, Blob& b) : visitor(v), blob(b) {}
00116 
00117     template <class T> result_type operator()(T*) {
00118         return visitor(*reinterpret_cast<T*>(blob.get()));
00119     }
00120 };
00121     
00122 template <class V> typename V::result_type MapValue::apply_visitor(V& v) {
00123     VisitVisitor<V> visitor(v, blob);
00124     return qpid::amqp_0_10::apply_visitor(visitor, code);
00125 }
00126 
00127 template <class R> struct MapValue::GetVisitor {
00128     typedef R* result_type;
00129     const MapValue::Blob& blob;
00130 
00131     GetVisitor(const MapValue::Blob& b) : blob(b) {}
00132 
00133     R* operator()(R& r) { return &r; }
00134     template <class T> R* operator()(T&) { return 0; }
00135 };
00136     
00137 template <class D> struct MapValue::DecodeVisitor {
00138     typedef void result_type;
00139     MapValue::Blob& blob;
00140     D& decoder;
00141     DecodeVisitor(Blob& b, D& d) : blob(b), decoder(d) {}
00142     
00143     template <class T> void operator()(T*) {
00144         T t;
00145         decoder(t);
00146         blob = t;
00147     }
00148 };
00149 
00150 template <class T> T* MapValue::get() { return apply_visitor(GetVisitor<T>(blob)); }
00151 template <class T> const T* MapValue::get() const { return apply_visitor(GetVisitor<const T>()); }
00152 
00153 template <class V> typename V::result_type MapValue::apply_visitor(const V& v) {
00154     return apply_visitor(const_cast<V&>(v));
00155 }
00156 
00157 template <class S> void Map::encode(S& s) const {
00158     // FIXME aconway 2008-04-03: replace preview mapping with 0-10 mapping:
00159     // s(contentSize())(uint32_t(size())); // size, count
00160     s(contentSize());
00161     for (const_iterator i = begin(); i != end(); ++i)
00162         s(i->first)(i->second); // key (type value)
00163 }
00164 
00165 template <class S> void Map::decode(S& s) {
00166     uint32_t decodedSize /*, count*/;
00167     // FIXME aconway 2008-04-03: replace preview mapping with 0-10 mapping:
00168     // s(contentSize())(uint32_t(size())); // size, count
00169     // s(decodedSize)(count);
00170     s(decodedSize);
00171     typename S::ScopedLimit l(s, decodedSize); // Make sure we don't overrun.
00172     // FIXME aconway 2008-04-03:  replace preview with 0-10:
00173     // for ( ; count > 0; --count) {
00174     while (s.getLimit() > 0) {
00175         key_type k; MapValue v;
00176         s(k)(v);
00177         insert(value_type(k,v));
00178     }
00179 }
00180 
00181 
00182 }} // namespace qpid::amqp_0_10
00183 
00184 #endif  

Generated on Thu Apr 10 11:08:17 2008 for Qpid by  doxygen 1.4.7