#ifndef QPID_AMQP_0_10_CODEC_H #define QPID_AMQP_0_10_CODEC_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 "built_in_types.h" #include "qpid/Serializer.h" #include #include #include #include namespace qpid { namespace amqp_0_10 { /** * AMQP 0-10 encoding and decoding. */ struct Codec { // FIXME aconway 2008-02-29: drop this wrapper? /** Encode to an output byte iterator */ template class Encode : public Serializer > { public: Encode(OutIter o) : out(o) {} using Serializer >::operator(); template typename boost::enable_if, Encode&>::type operator()(T x) { endianize(x); raw(&x, sizeof(x)); return *this; } // FIXME aconway 2008-02-20: correct float encoading? template typename boost::enable_if, Encode&>::type operator()(const T& x) { raw(&x, sizeof(x)); return *this; } template Encode& operator()(Iter begin, Iter end) { std::for_each(begin, end, *this); return *this; } void raw(const void* p, size_t n) { std::copy((const char*)p, (const char*)p+n, out); } private: OutIter out; }; template class Decode : public Serializer > { public: Decode(InIter i) : in(i) {} static const bool IS_DECODER=true; using Serializer >::operator(); template typename boost::enable_if, Decode&>::type operator()(T& x) { raw(&x, sizeof(x)); endianize(x); return *this; } template typename boost::enable_if, Decode&>::type operator()(T& x) { raw(&x, sizeof(x)); return *this; } template Decode& operator()(SerializableString& str) { SizeType n; (*this)(n); str.resize(n); std::for_each(str.begin(), str.end(), *this); return *this; } template Decode& operator()(Iter begin, Iter end) { std::for_each(begin, end, *this); return *this; } void raw(void *p, size_t n) { // FIXME aconway 2008-02-29: requires random access iterator, // does this optimize to memcpy? Is there a better way? std::copy(in, in+n, (char*)p); in += n; } private: InIter in; }; class Size : public Serializer { public: Size() : size(0) {} operator size_t() const { return size; } using Serializer::operator(); template typename boost::enable_if, Size&>::type operator()(const T&) { size += sizeof(T); return *this; } template Size& operator()(const SerializableString& str) { size += sizeof(SizeType) + str.size()*sizeof(T); return *this; } template Size& operator()(const Iter& a, const Iter& b) { size += (b-a)*sizeof(*a); return *this; } void raw(const void*, size_t n){ size += n; } private: size_t size; }; template static Decode decode(const OutIter &i) { return Decode(i); } template static Encode encode(InIter i) { return Encode(i); } template static size_t size(const T& x) { return Size()(x); } private: template static inline void endianize(T& value) { #ifdef BOOST_LITTLE_ENDIAN std::reverse((char*)&value, (char*)&value+sizeof(value)); #else (void)value; // Avoid unused var warnings. #endif } static inline void endianize(char&) {} static inline void endianize(uint8_t&) {} static inline void endianize(int8_t&) {} }; }} // namespace qpid::amqp_0_10 #endif /*!QPID_AMQP_0_10_CODEC_H*/