#ifndef QPID_SERIALIZER_H #define QPID_SERIALIZER_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 an * "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 #include #include "qpid/Exception.h" // FIXME aconway 2008-04-03: proper exception class. namespace qpid { /** * Overload for types that do not provide a serialize() member. * It should retrun a wrapper holding a reference to t that implements * serialize() */ template T& serializable(T& t) { return t; } /** Serialize std::pair */ template struct SerializablePair { std::pair& value; SerializablePair(std::pair& x) : value(x) {} template void serialize(S& s) { s(value.first)(value.second); } }; template SerializablePair serializable(std::pair& p) { return SerializablePair(p); } /** * Base class for all serializers. * Derived serializers inherit from either Encoder or Decoder. * Serializers can be used as functors or static_visitors. */ template class Serializer { public: /** Temporarily set a lower relative limit on the serializer */ class ScopedLimit { public: ScopedLimit(Serializer& s, size_t l) : serializer(s), save(serializer.setLimit(l)) {} ~ScopedLimit() { serializer.setAbsLimit(save); } private: Serializer& serializer; size_t save; }; static size_t maxLimit() { return std::numeric_limits::max(); } Serializer() : bytes(0), limit(maxLimit()) {} typedef Derived& result_type; // unary functor requirement. /** Wrapper functor to pass serializer functors by reference. */ template struct Ref { typedef typename S::result_type result_type; S& s; Ref(S& ss) : s(ss) {} template result_type operator()(T& x) { return s(x); } template result_type operator()(const T& x) { return s(x); } }; /** Reference wrapper to pass serializers by reference, * e.g. to std:: functions that take functors. */ template static Ref ref(S& s) { return Ref(s); } /** Generic rule to serialize an iterator range */ template Derived& operator()(Iter begin, Iter end) { std::for_each(begin, end, ref(this->self())); return self(); } /** Set limit relative to current position. * @return old absolute limit. */ size_t setLimit(size_t n) { size_t l=limit; limit = bytes+n; return l; } /** Get the max number of bytes that can be processed under the * current limit. */ size_t bytesRemaining() const { return limit - bytes; } /** Set absolute limit. */ void setAbsLimit(size_t n) { limit = n; if (bytes > limit) throw Exception("Framing error: data overrun"); // FIXME aconway 2008-04-03: proper exception. } protected: Derived& self() { return *static_cast(this); } void addBytes(size_t n) { size_t newBytes=bytes+n; if (newBytes > limit) throw Exception("Framing error: data overrun"); // FIXME aconway 2008-04-03: proper exception. bytes = newBytes; } private: void checkLimit() { } size_t bytes; // how many bytes serialized. size_t limit; // bytes may not exceed this limit. }; /** * Base class for encoders, provides generic encode functions. * * A derived encoder must provide operator(const T&) to encode all * primitive types T. */ template class EncoderBase : public Serializer { public: using Serializer::operator(); using Serializer::self; /** Default op() for non-primitive types. */ template Derived& operator()(const T& t) { serializable(const_cast(t)).serialize(self()); return self(); } /** Split serialize() into encode()/decode() */ template Derived& split(const T& t) { t.encode(self()); return self(); } }; /** * Base class for decoders, provides generic decode functions. * * A derived encoder must provide operator(T&) to encode all * primitive types T. */ template class DecoderBase : public Serializer { public: using Serializer::operator(); using Serializer::self; /** Default op() for non-primitive types. */ template Derived& operator()(T& t) { serializable(t).serialize(self()); return self(); } /** Split serialize() into encode()/decode() */ template Derived& split(T& t) { t.decode(self()); return self(); } }; /** Serialize a type by converting it to/from another type. * To serialize type Foo by converting to/from type Bar create * a serializable() overload like this: * * SerializeAs serializable(Foo& t) { return SerializeAs(t); } */ template struct SerializeAs { Type& value; SerializeAs(Type & t) : value(t) {} template void serialize(S& s) { s.split(*this); } template void encode(S& s) const { s(AsType(value)); } template void decode(S& s) { AsType x; s(x); value=Type(x); } }; } // namespace qpid #endif /*!QPID_SERIALIZER_H*/