diff options
Diffstat (limited to 'trunk/qpid/cpp/src/qpid/amqp_0_10/Map.h')
-rw-r--r-- | trunk/qpid/cpp/src/qpid/amqp_0_10/Map.h | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/trunk/qpid/cpp/src/qpid/amqp_0_10/Map.h b/trunk/qpid/cpp/src/qpid/amqp_0_10/Map.h new file mode 100644 index 0000000000..4093b1a0aa --- /dev/null +++ b/trunk/qpid/cpp/src/qpid/amqp_0_10/Map.h @@ -0,0 +1,188 @@ +#ifndef QPID_AMQP_0_10_MAP_H +#define QPID_AMQP_0_10_MAP_H + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on ang + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "qpid/Exception.h" +#include "qpid/amqp_0_10/built_in_types.h" +#include "qpid/amqp_0_10/UnknownType.h" +#include "qpid/amqp_0_10/CodeForType.h" +#include "qpid/amqp_0_10/TypeForCode.h" +#include "qpid/amqp_0_10/Codec.h" +#include "qpid/framing/Blob.h" +#include <map> +#include <string> +#include <iosfwd> + +namespace qpid { +namespace amqp_0_10 { + +class Map; + +class MapValue { + public: + struct BadTypeException : public Exception {}; + + template <class R> struct Visitor { typedef R result_type; }; + + MapValue(); + MapValue(const MapValue& x); + template <class T> explicit MapValue(const T& t); + template <class T> MapValue& operator=(const T& t); + + template <class T> T* get(); + template <class T> const T* get() const; + + template <class V> typename V::result_type apply_visitor(V&); + template <class V> typename V::result_type apply_visitor(const V&); + + uint8_t getCode() const { return code; } + + bool operator==(const MapValue&) const; + + template <class S> void serialize(S& s) { s(code); s.split(*this); } + template <class S> void encode(S& s) const { + const_cast<MapValue*>(this)->apply_visitor(s); + } + template <class S> void decode(S& s) { + DecodeVisitor<S> dv(blob, s); + qpid::amqp_0_10::apply_visitor(dv, code); + } + + + private: + // TODO aconway 2008-04-15: Estimate required size, we will get a + // compile error from static_assert in Blob.h if the estimate is too + // low. We can't use sizeof() directly because #include Struct32.h + // creates a circular dependency. Needs a better solution. + static const size_t SIZE=256; + typedef framing::Blob<SIZE> Blob; + + template <class V> struct VisitVisitor; + template <class T> struct GetVisitor; + template <class D> struct DecodeVisitor; + + uint8_t code; + Blob blob; +}; + +class Map : public std::map<Str8, MapValue> { + public: + template <class S> void serialize(S& s) { s.split(*this); } + template <class S> void encode(S& s) const; + // Shortcut calculation for size. + void encode(Codec::Size& s) const { s.raw(0, contentSize() + 4/*size*/); } + + template <class S> void decode(S& s); + + private: + uint32_t contentSize() const; +}; + +std::ostream& operator<<(std::ostream&, const MapValue&); +std::ostream& operator<<(std::ostream&, const Map::value_type&); +std::ostream& operator<<(std::ostream&, const Map&); + +using framing::in_place; + +template <class T> MapValue::MapValue(const T& t) : code(codeFor(t)), blob(in_place<t>()) {} + +template <class T> MapValue& MapValue::operator=(const T& t) { + code=codeFor(t); + blob=t; + return *this; +} + +template <class V> struct MapValue::VisitVisitor { + typedef typename V::result_type result_type; + V& visitor; + Blob& blob; + VisitVisitor(V& v, Blob& b) : visitor(v), blob(b) {} + + template <class T> result_type operator()(T*) { + return visitor(*reinterpret_cast<T*>(blob.get())); + } +}; + +template <class V> typename V::result_type MapValue::apply_visitor(V& v) { + VisitVisitor<V> visitor(v, blob); + return qpid::amqp_0_10::apply_visitor(visitor, code); +} + +template <class R> struct MapValue::GetVisitor { + typedef R* result_type; + const MapValue::Blob& blob; + + GetVisitor(const MapValue::Blob& b) : blob(b) {} + + R* operator()(R& r) { return &r; } + template <class T> R* operator()(T&) { return 0; } +}; + +template <class D> struct MapValue::DecodeVisitor { + typedef void result_type; + MapValue::Blob& blob; + D& decoder; + DecodeVisitor(Blob& b, D& d) : blob(b), decoder(d) {} + + template <class T> void operator()(T*) { + T t; + decoder(t); + blob = t; + } +}; + +template <class T> T* MapValue::get() { return apply_visitor(GetVisitor<T>(blob)); } +template <class T> const T* MapValue::get() const { return apply_visitor(GetVisitor<const T>()); } + +template <class V> typename V::result_type MapValue::apply_visitor(const V& v) { + return apply_visitor(const_cast<V&>(v)); +} + +template <class S> void Map::encode(S& s) const { + // FIXME aconway 2008-04-03: replace preview mapping with 0-10 mapping: + // s(contentSize())(uint32_t(size())); // size, count + s(contentSize()); + for (const_iterator i = begin(); i != end(); ++i) + s(i->first)(i->second); // key (type value) +} + +template <class S> void Map::decode(S& s) { + uint32_t decodedSize /*, count*/; + // FIXME aconway 2008-04-03: replace preview mapping with 0-10 mapping: + // s(contentSize())(uint32_t(size())); // size, count + // s(decodedSize)(count); + s(decodedSize); + typename S::ScopedLimit l(s, decodedSize); // Make sure we don't overrun. + // FIXME aconway 2008-04-03: replace preview with 0-10: + // for ( ; count > 0; --count) { + while (s.bytesRemaining() > 0) { + key_type k; MapValue v; + s(k)(v); + insert(value_type(k,v)); + } +} + + +}} // namespace qpid::amqp_0_10 + +#endif /*!QPID_AMQP_0_10_MAP_H*/ |