Program Listing for File Cdr.h

Return to documentation for file (include/fastcdr/Cdr.h)

// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed 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.

#ifndef _FASTCDR_CDR_H_
#define _FASTCDR_CDR_H_

#include <array>
#include <bitset>
#include <cassert>
#include <cstdint>
#include <cstring>
#include <functional>
#include <map>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>

#include "fastcdr_dll.h"

#include "CdrEncoding.hpp"
#include "cdr/fixed_size_string.hpp"
#include "detail/container_recursive_inspector.hpp"
#include "exceptions/BadParamException.h"
#include "exceptions/Exception.h"
#include "exceptions/NotEnoughMemoryException.h"
#include "FastBuffer.h"
#include "xcdr/external.hpp"
#include "xcdr/MemberId.hpp"
#include "xcdr/optional.hpp"

#if !__APPLE__ && !__FreeBSD__ && !__VXWORKS__
#include <malloc.h>
#else
#include <stdlib.h>
#endif // if !__APPLE__ && !__FreeBSD__ && !__VXWORKS__

namespace eprosima {
namespace fastcdr {

class Cdr;

template<class _T>
extern void serialize(
        Cdr&,
        const _T&);

template<class _T>
extern void deserialize(
        Cdr&,
        _T&);

class Cdr
{
public:

    typedef enum : uint8_t
    {
        BIG_ENDIANNESS = 0x0,
        LITTLE_ENDIANNESS = 0x1
    } Endianness;

    Cdr_DllAPI static const Endianness DEFAULT_ENDIAN;

    typedef enum
    {
        SHORT_HEADER,
        LONG_HEADER,
        AUTO_WITH_SHORT_HEADER_BY_DEFAULT,
        AUTO_WITH_LONG_HEADER_BY_DEFAULT
    } XCdrHeaderSelection;

    class state
    {
        friend class Cdr;

    public:

        Cdr_DllAPI state(
                const Cdr& cdr);

        Cdr_DllAPI state(
                const state& state);


        Cdr_DllAPI bool operator ==(
                const state& other_state) const;

    private:

        state& operator =(
                const state& state) = delete;

        const FastBuffer::iterator offset_;

        const FastBuffer::iterator origin_;

        bool swap_bytes_ {false};

        size_t last_data_size_ {0};

        MemberId next_member_id_;

        uint32_t member_size_ {0};

        XCdrHeaderSelection header_selection_ {XCdrHeaderSelection::AUTO_WITH_SHORT_HEADER_BY_DEFAULT};

        XCdrHeaderSelection header_serialized_ {XCdrHeaderSelection::SHORT_HEADER};

        EncodingAlgorithmFlag previous_encoding_ {EncodingAlgorithmFlag::PLAIN_CDR2};
    };

    Cdr_DllAPI Cdr(
            FastBuffer& cdr_buffer,
            const Endianness endianness = DEFAULT_ENDIAN,
            const CdrVersion cdr_version = XCDRv2);

    Cdr_DllAPI Cdr& read_encapsulation();

    Cdr_DllAPI Cdr& serialize_encapsulation();

    Cdr_DllAPI CdrVersion get_cdr_version() const;

    Cdr_DllAPI EncodingAlgorithmFlag get_encoding_flag() const;

    Cdr_DllAPI bool set_encoding_flag(
            EncodingAlgorithmFlag encoding_flag);

    Cdr_DllAPI std::array<uint8_t, 2> get_dds_cdr_options() const;

    Cdr_DllAPI void set_dds_cdr_options(
            const std::array<uint8_t, 2>& options);

    Cdr_DllAPI void change_endianness(
            Endianness endianness);

    Cdr_DllAPI Endianness endianness() const;

    Cdr_DllAPI bool jump(
            size_t num_bytes);

    Cdr_DllAPI void reset();

    Cdr_DllAPI char* get_buffer_pointer();

    Cdr_DllAPI char* get_current_position();

    Cdr_DllAPI size_t get_serialized_data_length() const;

    inline static size_t alignment(
            size_t current_alignment,
            size_t data_size)
    {
        return (data_size - (current_alignment % data_size)) & (data_size - 1);
    }

    Cdr_DllAPI state get_state() const;

    Cdr_DllAPI void set_state(
            const state& state);

    Cdr_DllAPI bool move_alignment_forward(
            size_t num_bytes);

    inline void reset_alignment()
    {
        origin_ = offset_;
        last_data_size_ = 0;
    }

    template<class _T>
    inline Cdr& operator <<(
            const _T& value)
    {
        if (MEMBER_ID_INVALID == next_member_id_)
        {
            serialize(value);
        }
        else
        {
            serialize_member(next_member_id_, value);

        }

        return *this;
    }

    template<class _T>
    inline Cdr& operator >>(
            _T& value)
    {
        if (MEMBER_ID_INVALID == next_member_id_)
        {
            deserialize(value);
        }
        else
        {
            deserialize_member(value);
        }
        return *this;
    }

    template<class _T, typename std::enable_if<!std::is_enum<_T>::value>::type* = nullptr, typename = void>
    Cdr& serialize(
            const _T& value)
    {
        eprosima::fastcdr::serialize(*this, value);
        return *this;
    }

    template<class _T>
    Cdr& serialize(
            const _T& value,
            Endianness endianness)
    {
        bool aux_swap = swap_bytes_;
        swap_bytes_ = (swap_bytes_ && (static_cast<Endianness>(endianness_) == endianness)) ||
                (!swap_bytes_ && (static_cast<Endianness>(endianness_) != endianness));

        try
        {
            serialize(value);
            swap_bytes_ = aux_swap;
        }
        catch (exception::Exception& ex)
        {
            swap_bytes_ = aux_swap;
            ex.raise();
        }

        return *this;
    }

    template<class _T,
            typename std::enable_if<std::is_enum<_T>::value>::type* = nullptr,
            typename std::enable_if<std::is_same<typename std::underlying_type<_T>::type,
            int32_t>::value>::type* = nullptr>
    Cdr& serialize(
            const _T& value)
    {
        return serialize(static_cast<int32_t>(value));
    }

    template<class _T,
            typename std::enable_if<std::is_enum<_T>::value>::type* = nullptr,
            typename std::enable_if<std::is_same<typename std::underlying_type<_T>::type,
            uint32_t>::value>::type* = nullptr>
    Cdr& serialize(
            const _T& value)
    {
        return serialize(static_cast<uint32_t>(value));
    }

    template<class _T,
            typename std::enable_if<std::is_enum<_T>::value>::type* = nullptr,
            typename std::enable_if<std::is_same<typename std::underlying_type<_T>::type,
            int16_t>::value>::type* = nullptr>
    Cdr& serialize(
            const _T& value)
    {
        return serialize(static_cast<int16_t>(value));
    }

    template<class _T,
            typename std::enable_if<std::is_enum<_T>::value>::type* = nullptr,
            typename std::enable_if<std::is_same<typename std::underlying_type<_T>::type,
            uint16_t>::value>::type* = nullptr>
    Cdr& serialize(
            const _T& value)
    {
        return serialize(static_cast<uint16_t>(value));
    }

    template<class _T,
            typename std::enable_if<std::is_enum<_T>::value>::type* = nullptr,
            typename std::enable_if<std::is_same<typename std::underlying_type<_T>::type,
            int8_t>::value>::type* = nullptr>
    Cdr& serialize(
            const _T& value)
    {
        return serialize(static_cast<int8_t>(value));
    }

    template<class _T,
            typename std::enable_if<std::is_enum<_T>::value>::type* = nullptr,
            typename std::enable_if<std::is_same<typename std::underlying_type<_T>::type,
            uint8_t>::value>::type* = nullptr>
    Cdr& serialize(
            const _T& value)
    {
        return serialize(static_cast<uint8_t>(value));
    }

    Cdr_DllAPI Cdr& serialize(
            const uint8_t& octet_t);

    Cdr_DllAPI Cdr& serialize(
            const char char_t);

    Cdr_DllAPI Cdr& serialize(
            const int8_t int8);

    Cdr_DllAPI Cdr& serialize(
            const uint16_t ushort_t);

    Cdr_DllAPI Cdr& serialize(
            const int16_t short_t);

    Cdr_DllAPI Cdr& serialize(
            const uint32_t ulong_t);

    Cdr_DllAPI Cdr& serialize(
            const int32_t long_t);

    Cdr_DllAPI Cdr& serialize(
            const wchar_t wchar);

    Cdr_DllAPI Cdr& serialize(
            const uint64_t ulonglong_t);

    Cdr_DllAPI Cdr& serialize(
            const int64_t longlong_t);

    Cdr_DllAPI Cdr& serialize(
            const float float_t);

    Cdr_DllAPI Cdr& serialize(
            const double double_t);

    Cdr_DllAPI Cdr& serialize(
            const long double ldouble_t);

    Cdr_DllAPI Cdr& serialize(
            const bool bool_t);

    Cdr_DllAPI Cdr& serialize(
            char* string_t);

    Cdr_DllAPI Cdr& serialize(
            const char* string_t);

    Cdr_DllAPI Cdr& serialize(
            const wchar_t* string_t);

    TEMPLATE_SPEC
    Cdr& serialize(
            const std::string& string_t)
    {
        // Check there are no null characters in the string.
        const char* c_str = string_t.c_str();
        const auto str_len = strlen(c_str);
        if (string_t.size() > str_len)
        {
            throw exception::BadParamException("The string contains null characters");
        }

        return serialize_sequence(c_str, str_len + 1);
    }

    TEMPLATE_SPEC
    Cdr& serialize(
            const std::wstring& string_t)
    {
        return serialize(string_t.c_str());
    }

    template <size_t MAX_CHARS>
    Cdr& serialize(
            const fixed_string<MAX_CHARS>& value)
    {
        return serialize(value.c_str());
    }

    template<class _T, size_t _Size>
    Cdr& serialize(
            const std::array<_T, _Size>& array_t)
    {
        if (!is_multi_array_primitive(&array_t))
        {
            Cdr::state dheader_state {allocate_xcdrv2_dheader()};

            serialize_array(array_t.data(), array_t.size());

            set_xcdrv2_dheader(dheader_state);
        }
        else
        {
            serialize_array(array_t.data(), array_t.size());
        }

        return *this;
    }

    template<class _T, typename std::enable_if<!std::is_enum<_T>::value &&
            !std::is_arithmetic<_T>::value>::type* = nullptr>
    Cdr& serialize(
            const std::vector<_T>& vector_t)
    {
        Cdr::state dheader_state {allocate_xcdrv2_dheader()};

        serialize(static_cast<int32_t>(vector_t.size()));

        try
        {
            serialize_array(vector_t.data(), vector_t.size());
        }
        catch (exception::Exception& ex)
        {
            set_state(dheader_state);
            ex.raise();
        }

        set_xcdrv2_dheader(dheader_state);

        return *this;
    }

    template<class _T, typename std::enable_if<std::is_enum<_T>::value ||
            std::is_arithmetic<_T>::value>::type* = nullptr>
    Cdr& serialize(
            const std::vector<_T>& vector_t)
    {
        state state_before_error(*this);

        serialize(static_cast<int32_t>(vector_t.size()));

        try
        {
            serialize_array(vector_t.data(), vector_t.size());
        }
        catch (exception::Exception& ex)
        {
            set_state(state_before_error);
            ex.raise();
        }

        if (CdrVersion::XCDRv2 == cdr_version_)
        {
            serialized_member_size_ = get_serialized_member_size<_T>();
        }

        return *this;
    }

    TEMPLATE_SPEC
    Cdr& serialize(
            const std::vector<bool>& vector_t)
    {
        return serialize_bool_sequence(vector_t);
    }

    template<class _K, class _T, typename std::enable_if<!std::is_enum<_T>::value &&
            !std::is_arithmetic<_T>::value>::type* = nullptr>
    Cdr& serialize(
            const std::map<_K, _T>& map_t)
    {
        Cdr::state dheader_state {allocate_xcdrv2_dheader()};

        serialize(static_cast<int32_t>(map_t.size()));

        try
        {
            for (auto it_pair = map_t.begin(); it_pair != map_t.end(); ++it_pair)
            {
                serialize(it_pair->first);
                serialize(it_pair->second);
            }
        }
        catch (exception::Exception& ex)
        {
            set_state(dheader_state);
            ex.raise();
        }

        set_xcdrv2_dheader(dheader_state);

        return *this;
    }

    template<class _K, class _T, typename std::enable_if<std::is_enum<_T>::value ||
            std::is_arithmetic<_T>::value>::type* = nullptr>
    Cdr& serialize(
            const std::map<_K, _T>& map_t)
    {
        state state_(*this);

        serialize(static_cast<int32_t>(map_t.size()));

        try
        {
            for (auto it_pair = map_t.begin(); it_pair != map_t.end(); ++it_pair)
            {
                serialize(it_pair->first);
                serialize(it_pair->second);
            }
        }
        catch (exception::Exception& ex)
        {
            set_state(state_);
            ex.raise();
        }

        return *this;
    }

    template<size_t N, typename std::enable_if < (N < 9) > ::type* = nullptr>
    Cdr& serialize(
            const std::bitset<N>& value)
    {
        return serialize(static_cast<uint8_t>(value.to_ulong()));
    }

    template<size_t N, typename std::enable_if < (8 < N && N < 17) > ::type* = nullptr>
    Cdr& serialize(
            const std::bitset<N>& value)
    {
        return serialize(static_cast<uint16_t>(value.to_ulong()));
    }

    template<size_t N, typename std::enable_if < (16 < N && N < 33) > ::type* = nullptr>
    Cdr& serialize(
            const std::bitset<N>& value)
    {
        return serialize(static_cast<uint32_t>(value.to_ulong()));
    }

    template<size_t N, typename std::enable_if < (32 < N && N < 65) > ::type* = nullptr>
    Cdr& serialize(
            const std::bitset<N>& value)
    {
        return serialize(static_cast<uint64_t>(value.to_ullong()));
    }

    template<class _T>
    Cdr& serialize_array(
            const _T* value,
            size_t num_elements)
    {
        for (size_t count = 0; count < num_elements; ++count)
        {
            serialize(value[count]);
        }
        return *this;
    }

    template<class _T>
    Cdr& serialize_array(
            const _T* type_t,
            size_t num_elements,
            Endianness endianness)
    {
        bool aux_swap = swap_bytes_;
        swap_bytes_ = (swap_bytes_ && (static_cast<Endianness>(endianness_) == endianness)) ||
                (!swap_bytes_ && (static_cast<Endianness>(endianness_) != endianness));

        try
        {
            serialize_array(type_t, num_elements);
            swap_bytes_ = aux_swap;
        }
        catch (exception::Exception& ex)
        {
            swap_bytes_ = aux_swap;
            ex.raise();
        }

        return *this;
    }

    TEMPLATE_SPEC
    Cdr& serialize_array(
            const uint8_t* octet_t,
            size_t num_elements)
    {
        return serialize_array(reinterpret_cast<const char*>(octet_t), num_elements);
    }

    Cdr_DllAPI Cdr& serialize_array(
            const char* char_t,
            size_t num_elements);

    TEMPLATE_SPEC
    Cdr& serialize_array(
            const int8_t* int8,
            size_t num_elements)
    {
        return serialize_array(reinterpret_cast<const char*>(int8), num_elements);
    }

    TEMPLATE_SPEC
    Cdr& serialize_array(
            const uint16_t* ushort_t,
            size_t num_elements)
    {
        return serialize_array(reinterpret_cast<const int16_t*>(ushort_t), num_elements);
    }

    Cdr_DllAPI Cdr& serialize_array(
            const int16_t* short_t,
            size_t num_elements);

    TEMPLATE_SPEC
    Cdr& serialize_array(
            const uint32_t* ulong_t,
            size_t num_elements)
    {
        return serialize_array(reinterpret_cast<const int32_t*>(ulong_t), num_elements);
    }

    Cdr_DllAPI Cdr& serialize_array(
            const int32_t* long_t,
            size_t num_elements);

    Cdr_DllAPI Cdr& serialize_array(
            const wchar_t* wchar,
            size_t num_elements);

    TEMPLATE_SPEC
    Cdr& serialize_array(
            const uint64_t* ulonglong_t,
            size_t num_elements)
    {
        return serialize_array(reinterpret_cast<const int64_t*>(ulonglong_t), num_elements);
    }

    Cdr_DllAPI Cdr& serialize_array(
            const int64_t* longlong_t,
            size_t num_elements);

    Cdr_DllAPI Cdr& serialize_array(
            const float* float_t,
            size_t num_elements);

    Cdr_DllAPI Cdr& serialize_array(
            const double* double_t,
            size_t num_elements);

    Cdr_DllAPI Cdr& serialize_array(
            const long double* ldouble_t,
            size_t num_elements);

    Cdr_DllAPI Cdr& serialize_array(
            const bool* bool_t,
            size_t num_elements);

    TEMPLATE_SPEC
    Cdr& serialize_array(
            const std::string* string_t,
            size_t num_elements)
    {
        for (size_t count = 0; count < num_elements; ++count)
        {
            serialize(string_t[count].c_str());
        }
        return *this;
    }

    TEMPLATE_SPEC
    Cdr& serialize_array(
            const std::wstring* string_t,
            size_t num_elements)
    {
        for (size_t count = 0; count < num_elements; ++count)
        {
            serialize(string_t[count].c_str());
        }
        return *this;
    }

    template<size_t MAX_CHARS>
    Cdr& serialize_array(
            const fixed_string<MAX_CHARS>* value,
            size_t num_elements)
    {
        for (size_t count = 0; count < num_elements; ++count)
        {
            serialize(value[count].c_str());
        }
        return *this;
    }

    template<class _T, typename std::enable_if<std::is_enum<_T>::value ||
            std::is_arithmetic<_T>::value>::type* = nullptr>
    Cdr& serialize_array(
            const std::vector<_T>& value)
    {
        serialize_array(value.data(), value.size());

        return *this;
    }

    template<class _T, typename std::enable_if<!std::is_enum<_T>::value &&
            !std::is_arithmetic<_T>::value>::type* = nullptr>
    Cdr& serialize_array(
            const std::vector<_T>& value)
    {
        Cdr::state dheader_state {allocate_xcdrv2_dheader()};

        serialize_array(value.data(), value.size());

        set_xcdrv2_dheader(dheader_state);

        return *this;
    }

    template<class _T>
    Cdr& serialize_array(
            const std::vector<_T>& value,
            Endianness endianness)
    {
        bool aux_swap = swap_bytes_;
        swap_bytes_ = (swap_bytes_ && (static_cast<Endianness>(endianness_) == endianness)) ||
                (!swap_bytes_ && (static_cast<Endianness>(endianness_) != endianness));

        try
        {
            serialize_array(value);
            swap_bytes_ = aux_swap;
        }
        catch (exception::Exception& ex)
        {
            swap_bytes_ = aux_swap;
            ex.raise();
        }

        return *this;
    }

    TEMPLATE_SPEC
    Cdr& serialize_array(
            const std::vector<bool>& value)
    {
        serialize_bool_array(value);

        return *this;
    }

    template<class _T, typename std::enable_if<!std::is_enum<_T>::value &&
            !std::is_arithmetic<_T>::value>::type* = nullptr>
    Cdr& serialize_sequence(
            const _T* sequence_t,
            size_t num_elements)
    {
        Cdr::state dheader_state {allocate_xcdrv2_dheader()};

        serialize(static_cast<int32_t>(num_elements));

        try
        {
            serialize_array(sequence_t, num_elements);
        }
        catch (exception::Exception& ex)
        {
            set_state(dheader_state);
            ex.raise();
        }

        set_xcdrv2_dheader(dheader_state);

        return *this;
    }

    template<class _T, typename std::enable_if<std::is_enum<_T>::value ||
            std::is_arithmetic<_T>::value>::type* = nullptr>
    Cdr& serialize_sequence(
            const _T* sequence_t,
            size_t num_elements)
    {
        state state_before_error(*this);

        serialize(static_cast<int32_t>(num_elements));

        try
        {
            serialize_array(sequence_t, num_elements);
        }
        catch (exception::Exception& ex)
        {
            set_state(state_before_error);
            ex.raise();
        }

        if (CdrVersion::XCDRv2 == cdr_version_)
        {
            serialized_member_size_ = get_serialized_member_size<_T>();
        }

        return *this;
    }

    template<class _T>
    Cdr& serialize_sequence(
            const _T* sequence_t,
            size_t num_elements,
            Endianness endianness)
    {
        bool aux_swap = swap_bytes_;
        swap_bytes_ = (swap_bytes_ && (static_cast<Endianness>(endianness_) == endianness)) ||
                (!swap_bytes_ && (static_cast<Endianness>(endianness_) != endianness));

        try
        {
            serialize_sequence(sequence_t, num_elements);
            swap_bytes_ = aux_swap;
        }
        catch (exception::Exception& ex)
        {
            swap_bytes_ = aux_swap;
            ex.raise();
        }

        return *this;
    }

    template<class _T, typename std::enable_if<!std::is_enum<_T>::value>::type* = nullptr, typename = void>
    Cdr& deserialize(
            _T& value)
    {
        eprosima::fastcdr::deserialize(*this, value);
        return *this;
    }

    template<class _T>
    Cdr& deserialize(
            _T& value,
            Endianness endianness)
    {
        bool aux_swap = swap_bytes_;
        swap_bytes_ = (swap_bytes_ && (static_cast<Endianness>(endianness_) == endianness)) ||
                (!swap_bytes_ && (static_cast<Endianness>(endianness_) != endianness));

        try
        {
            deserialize(value);
            swap_bytes_ = aux_swap;
        }
        catch (exception::Exception& ex)
        {
            swap_bytes_ = aux_swap;
            ex.raise();
        }

        return *this;
    }

    template<class _T,
            typename std::enable_if<std::is_enum<_T>::value>::type* = nullptr,
            typename std::enable_if<std::is_same<typename std::underlying_type<_T>::type,
            int32_t>::value>::type* = nullptr>
    Cdr& deserialize(
            _T& value)
    {
        int32_t decode_value {0};
        deserialize(decode_value);
        value = static_cast<_T>(decode_value);
        return *this;
    }

    template<class _T,
            typename std::enable_if<std::is_enum<_T>::value>::type* = nullptr,
            typename std::enable_if<std::is_same<typename std::underlying_type<_T>::type,
            uint32_t>::value>::type* = nullptr>
    Cdr& deserialize(
            _T& value)
    {
        uint32_t decode_value {0};
        deserialize(decode_value);
        value = static_cast<_T>(decode_value);
        return *this;
    }

    template<class _T,
            typename std::enable_if<std::is_enum<_T>::value>::type* = nullptr,
            typename std::enable_if<std::is_same<typename std::underlying_type<_T>::type,
            int16_t>::value>::type* = nullptr>
    Cdr& deserialize(
            _T& value)
    {
        int16_t decode_value {0};
        deserialize(decode_value);
        value = static_cast<_T>(decode_value);
        return *this;
    }

    template<class _T,
            typename std::enable_if<std::is_enum<_T>::value>::type* = nullptr,
            typename std::enable_if<std::is_same<typename std::underlying_type<_T>::type,
            uint16_t>::value>::type* = nullptr>
    Cdr& deserialize(
            _T& value)
    {
        uint16_t decode_value {0};
        deserialize(decode_value);
        value = static_cast<_T>(decode_value);
        return *this;
    }

    template<class _T,
            typename std::enable_if<std::is_enum<_T>::value>::type* = nullptr,
            typename std::enable_if<std::is_same<typename std::underlying_type<_T>::type,
            int8_t>::value>::type* = nullptr>
    Cdr& deserialize(
            _T& value)
    {
        int8_t decode_value {0};
        deserialize(decode_value);
        value = static_cast<_T>(decode_value);
        return *this;
    }

    template<class _T,
            typename std::enable_if<std::is_enum<_T>::value>::type* = nullptr,
            typename std::enable_if<std::is_same<typename std::underlying_type<_T>::type,
            uint8_t>::value>::type* = nullptr>
    Cdr& deserialize(
            _T& value)
    {
        uint8_t decode_value {0};
        deserialize(decode_value);
        value = static_cast<_T>(decode_value);
        return *this;
    }

    TEMPLATE_SPEC
    Cdr& deserialize(
            uint8_t& octet_t)
    {
        return deserialize(reinterpret_cast<char&>(octet_t));
    }

    Cdr_DllAPI Cdr& deserialize(
            char& char_t);

    TEMPLATE_SPEC
    Cdr& deserialize(
            int8_t& int8)
    {
        return deserialize(reinterpret_cast<char&>(int8));
    }

    TEMPLATE_SPEC
    Cdr& deserialize(
            uint16_t& ushort_t)
    {
        return deserialize(reinterpret_cast<int16_t&>(ushort_t));
    }

    Cdr_DllAPI Cdr& deserialize(
            int16_t& short_t);

    TEMPLATE_SPEC
    Cdr& deserialize(
            uint32_t& ulong_t)
    {
        return deserialize(reinterpret_cast<int32_t&>(ulong_t));
    }

    Cdr_DllAPI Cdr& deserialize(
            int32_t& long_t);

    TEMPLATE_SPEC
    Cdr& deserialize(
            wchar_t& wchar)
    {
        uint16_t ret;
        deserialize(ret);
        wchar = static_cast<wchar_t>(ret);
        return *this;
    }

    TEMPLATE_SPEC
    Cdr& deserialize(
            uint64_t& ulonglong_t)
    {
        return deserialize(reinterpret_cast<int64_t&>(ulonglong_t));
    }

    Cdr_DllAPI Cdr& deserialize(
            int64_t& longlong_t);

    Cdr_DllAPI Cdr& deserialize(
            float& float_t);

    Cdr_DllAPI Cdr& deserialize(
            double& double_t);

    Cdr_DllAPI Cdr& deserialize(
            long double& ldouble_t);

    Cdr_DllAPI Cdr& deserialize(
            bool& bool_t);

    Cdr_DllAPI Cdr& deserialize(
            char*& string_t);

    Cdr_DllAPI Cdr& deserialize(
            wchar_t*& string_t);

    TEMPLATE_SPEC
    Cdr& deserialize(
            std::string& string_t)
    {
        uint32_t length = 0;
        const char* str = read_string(length);
        string_t.assign(str, length);
        return *this;
    }

    TEMPLATE_SPEC
    Cdr& deserialize(
            std::wstring& string_t)
    {
        uint32_t length = 0;
        string_t = read_wstring(length);
        return *this;
    }

    template <size_t MAX_CHARS>
    Cdr& deserialize(
            fixed_string<MAX_CHARS>& value)
    {
        uint32_t length = 0;
        const char* str = read_string(length);
        value.assign(str, length);
        return *this;
    }

    template<class _T, size_t _Size>
    Cdr& deserialize(
            std::array<_T, _Size>& array_t)
    {
        if (CdrVersion::XCDRv2 == cdr_version_ && !is_multi_array_primitive(&array_t))
        {
            uint32_t dheader {0};
            deserialize(dheader);

            uint32_t count {0};
            auto offset = offset_;
            while (offset_ - offset < dheader && count < _Size)
            {
                deserialize_array(&array_t.data()[count], 1);
                ++count;
            }

            if (offset_ - offset != dheader)
            {
                throw exception::BadParamException("Member size greater than size specified by DHEADER");
            }
        }
        else
        {
            return deserialize_array(array_t.data(), array_t.size());
        }

        return *this;
    }

    template<class _T, typename std::enable_if<!std::is_enum<_T>::value &&
            !std::is_arithmetic<_T>::value>::type* = nullptr>
    Cdr& deserialize(
            std::vector<_T>& vector_t)
    {
        uint32_t sequence_length {0};

        if (CdrVersion::XCDRv2 == cdr_version_)
        {
            uint32_t dheader {0};
            deserialize(dheader);

            auto offset = offset_;

            deserialize(sequence_length);

            if (0 == sequence_length)
            {
                vector_t.clear();
                return *this;
            }
            else
            {
                vector_t.resize(sequence_length);
            }

            uint32_t count {0};
            while (offset_ - offset < dheader && count < sequence_length)
            {
                deserialize(vector_t.data()[count]);
                ++count;
            }

            if (offset_ - offset != dheader)
            {
                throw exception::BadParamException("Member size differs from the size specified by DHEADER");
            }
        }
        else
        {
            state state_before_error(*this);

            deserialize(sequence_length);

            if (sequence_length == 0)
            {
                vector_t.clear();
                return *this;
            }

            if ((end_ - offset_) < sequence_length)
            {
                set_state(state_before_error);
                throw exception::NotEnoughMemoryException(
                          exception::NotEnoughMemoryException::NOT_ENOUGH_MEMORY_MESSAGE_DEFAULT);
            }

            try
            {
                vector_t.resize(sequence_length);
                return deserialize_array(vector_t.data(), vector_t.size());
            }
            catch (exception::Exception& ex)
            {
                set_state(state_before_error);
                ex.raise();
            }
        }

        return *this;
    }

    template<class _T, typename std::enable_if<std::is_enum<_T>::value ||
            std::is_arithmetic<_T>::value>::type* = nullptr>
    Cdr& deserialize(
            std::vector<_T>& vector_t)
    {
        uint32_t sequence_length = 0;
        state state_before_error(*this);

        deserialize(sequence_length);

        if (sequence_length == 0)
        {
            vector_t.clear();
            return *this;
        }

        if ((end_ - offset_) < sequence_length)
        {
            set_state(state_before_error);
            throw exception::NotEnoughMemoryException(
                      exception::NotEnoughMemoryException::NOT_ENOUGH_MEMORY_MESSAGE_DEFAULT);
        }

        try
        {
            vector_t.resize(sequence_length);
            return deserialize_array(vector_t.data(), vector_t.size());
        }
        catch (exception::Exception& ex)
        {
            set_state(state_before_error);
            ex.raise();
        }

        return *this;
    }

    TEMPLATE_SPEC
    Cdr& deserialize(
            std::vector<bool>& vector_t)
    {
        return deserialize_bool_sequence(vector_t);
    }

    template<class _K, class _T, typename std::enable_if<!std::is_enum<_T>::value &&
            !std::is_arithmetic<_T>::value>::type* = nullptr>
    Cdr& deserialize(
            std::map<_K, _T>& map_t)
    {
        if (CdrVersion::XCDRv2 == cdr_version_)
        {
            uint32_t dheader {0};
            deserialize(dheader);

            auto offset = offset_;

            uint32_t map_length {0};
            deserialize(map_length);

            map_t.clear();

            uint32_t count {0};
            while (offset_ - offset < dheader && count < map_length)
            {
                _K key;
                _T val;
                deserialize(key);
                deserialize(val);
                map_t.emplace(std::pair<_K, _T>(std::move(key), std::move(val)));
                ++count;
            }

            if (offset_ - offset != dheader)
            {
                throw exception::BadParamException("Member size greater than size specified by DHEADER");
            }
        }
        else
        {
            uint32_t sequence_length = 0;
            state state_(*this);

            deserialize(sequence_length);

            map_t.clear();

            try
            {
                for (uint32_t i = 0; i < sequence_length; ++i)
                {
                    _K key;
                    _T value;
                    deserialize(key);
                    deserialize(value);
                    map_t.emplace(std::pair<_K, _T>(std::move(key), std::move(value)));
                }
            }
            catch (exception::Exception& ex)
            {
                set_state(state_);
                ex.raise();
            }
        }

        return *this;
    }

    template<class _K, class _T, typename std::enable_if<std::is_enum<_T>::value ||
            std::is_arithmetic<_T>::value>::type* = nullptr>
    Cdr& deserialize(
            std::map<_K, _T>& map_t)
    {
        uint32_t sequence_length = 0;
        state state_(*this);

        deserialize(sequence_length);

        try
        {
            for (uint32_t i = 0; i < sequence_length; ++i)
            {
                _K key;
                _T value;
                deserialize(key);
                deserialize(value);
                map_t.emplace(std::pair<_K, _T>(std::move(key), std::move(value)));
            }
        }
        catch (exception::Exception& ex)
        {
            set_state(state_);
            ex.raise();
        }

        return *this;
    }

    template<size_t N, typename std::enable_if < (N < 9) > ::type* = nullptr>
    Cdr& deserialize(
            std::bitset<N>& value)
    {
        uint8_t decode_value {0};
        deserialize(decode_value);
        value = decode_value;
        return *this;
    }

    template<size_t N, typename std::enable_if < (8 < N && N < 17) > ::type* = nullptr>
    Cdr& deserialize(
            std::bitset<N>& value)
    {
        uint16_t decode_value {0};
        deserialize(decode_value);
        value = decode_value;
        return *this;
    }

    template<size_t N, typename std::enable_if < (16 < N && N < 33) > ::type* = nullptr>
    Cdr& deserialize(
            std::bitset<N>& value)
    {
        uint32_t decode_value {0};
        deserialize(decode_value);
        value = decode_value;
        return *this;
    }

    template<size_t N, typename std::enable_if < (32 < N && N < 65) > ::type* = nullptr>
    Cdr& deserialize(
            std::bitset<N>& value)
    {
        uint64_t decode_value {0};
        deserialize(decode_value);
        value = decode_value;
        return *this;
    }

    template<class _T>
    Cdr& deserialize_array(
            _T* value,
            size_t num_elements)
    {
        for (size_t count = 0; count < num_elements; ++count)
        {
            deserialize(value[count]);
        }
        return *this;
    }

    template<class _T>
    Cdr& deserialize_array(
            _T* type_t,
            size_t num_elements,
            Endianness endianness)
    {
        bool aux_swap = swap_bytes_;
        swap_bytes_ = (swap_bytes_ && (static_cast<Endianness>(endianness_) == endianness)) ||
                (!swap_bytes_ && (static_cast<Endianness>(endianness_) != endianness));

        try
        {
            deserialize_array(type_t, num_elements);
            swap_bytes_ = aux_swap;
        }
        catch (exception::Exception& ex)
        {
            swap_bytes_ = aux_swap;
            ex.raise();
        }

        return *this;
    }

    TEMPLATE_SPEC
    Cdr& deserialize_array(
            uint8_t* octet_t,
            size_t num_elements)
    {
        return deserialize_array(reinterpret_cast<char*>(octet_t), num_elements);
    }

    Cdr_DllAPI Cdr& deserialize_array(
            char* char_t,
            size_t num_elements);

    TEMPLATE_SPEC
    Cdr& deserialize_array(
            int8_t* int8,
            size_t num_elements)
    {
        return deserialize_array(reinterpret_cast<char*>(int8), num_elements);
    }

    TEMPLATE_SPEC
    Cdr& deserialize_array(
            uint16_t* ushort_t,
            size_t num_elements)
    {
        return deserialize_array(reinterpret_cast<int16_t*>(ushort_t), num_elements);
    }

    Cdr_DllAPI Cdr& deserialize_array(
            int16_t* short_t,
            size_t num_elements);

    TEMPLATE_SPEC
    Cdr& deserialize_array(
            uint32_t* ulong_t,
            size_t num_elements)
    {
        return deserialize_array(reinterpret_cast<int32_t*>(ulong_t), num_elements);
    }

    Cdr_DllAPI Cdr& deserialize_array(
            int32_t* long_t,
            size_t num_elements);

    Cdr_DllAPI Cdr& deserialize_array(
            wchar_t* wchar,
            size_t num_elements);

    TEMPLATE_SPEC
    Cdr& deserialize_array(
            uint64_t* ulonglong_t,
            size_t num_elements)
    {
        return deserialize_array(reinterpret_cast<int64_t*>(ulonglong_t), num_elements);
    }

    Cdr_DllAPI Cdr& deserialize_array(
            int64_t* longlong_t,
            size_t num_elements);

    Cdr_DllAPI Cdr& deserialize_array(
            float* float_t,
            size_t num_elements);

    Cdr_DllAPI Cdr& deserialize_array(
            double* double_t,
            size_t num_elements);

    Cdr_DllAPI Cdr& deserialize_array(
            long double* ldouble_t,
            size_t num_elements);

    Cdr_DllAPI Cdr& deserialize_array(
            bool* bool_t,
            size_t num_elements);

    template<class _T, typename std::enable_if<std::is_enum<_T>::value ||
            std::is_arithmetic<_T>::value>::type* = nullptr>
    Cdr& deserialize_array(
            std::vector<_T>& value)
    {
        deserialize_array(value.data(), value.size());

        return *this;
    }

    template<class _T, typename std::enable_if<!std::is_enum<_T>::value &&
            !std::is_arithmetic<_T>::value>::type* = nullptr>
    Cdr& deserialize_array(
            std::vector<_T>& value)
    {
        if (CdrVersion::XCDRv2 == cdr_version_)
        {
            uint32_t dheader {0};
            deserialize(dheader);

            uint32_t count {0};
            auto offset = offset_;
            while (offset_ - offset < dheader && count < value.size())
            {
                deserialize_array(&value.data()[count], 1);
                ++count;
            }

            if (offset_ - offset != dheader)
            {
                throw exception::BadParamException("Member size greater than size specified by DHEADER");
            }
        }
        else
        {
            return deserialize_array(value.data(), value.size());
        }

        return *this;
    }

    template<class _T>
    Cdr& deserialize_array(
            std::vector<_T>& value,
            Endianness endianness)
    {
        bool aux_swap = swap_bytes_;
        swap_bytes_ = (swap_bytes_ && (static_cast<Endianness>(endianness_) == endianness)) ||
                (!swap_bytes_ && (static_cast<Endianness>(endianness_) != endianness));

        try
        {
            deserialize_array(value);
            swap_bytes_ = aux_swap;
        }
        catch (exception::Exception& ex)
        {
            swap_bytes_ = aux_swap;
            ex.raise();
        }

        return *this;
    }

    TEMPLATE_SPEC
    Cdr& deserialize_array(
            std::vector<bool>& value)
    {
        deserialize_bool_array(value);

        return *this;
    }

    template<class _T, typename std::enable_if<!std::is_enum<_T>::value &&
            !std::is_arithmetic<_T>::value>::type* = nullptr>
    Cdr& deserialize_sequence(
            _T*& sequence_t,
            size_t& num_elements)
    {
        uint32_t sequence_length {0};

        if (CdrVersion::XCDRv2 == cdr_version_)
        {
            uint32_t dheader {0};
            deserialize(dheader);

            auto offset = offset_;

            deserialize(sequence_length);

            try
            {
                sequence_t = reinterpret_cast<_T*>(calloc(sequence_length, sizeof(_T)));

                uint32_t count {0};
                while (offset_ - offset < dheader && count < sequence_length)
                {
                    deserialize(sequence_t[count]);
                    ++count;
                }

                if (offset_ - offset != dheader)
                {
                    throw exception::BadParamException("Member size greater than size specified by DHEADER");
                }
            }
            catch (exception::Exception& ex)
            {
                free(sequence_t);
                sequence_t = NULL;
                ex.raise();
            }
        }
        else
        {
            state state_before_error(*this);

            deserialize(sequence_length);

            if ((end_ - offset_) < sequence_length)
            {
                set_state(state_before_error);
                throw exception::NotEnoughMemoryException(
                          exception::NotEnoughMemoryException::NOT_ENOUGH_MEMORY_MESSAGE_DEFAULT);
            }

            try
            {
                sequence_t = reinterpret_cast<_T*>(calloc(sequence_length, sizeof(_T)));
                deserialize_array(sequence_t, sequence_length);
            }
            catch (exception::Exception& ex)
            {
                free(sequence_t);
                sequence_t = NULL;
                set_state(state_before_error);
                ex.raise();
            }
        }

        num_elements = sequence_length;
        return *this;
    }

    template<class _T, typename std::enable_if<std::is_enum<_T>::value ||
            std::is_arithmetic<_T>::value>::type* = nullptr>
    Cdr& deserialize_sequence(
            _T*& sequence_t,
            size_t& num_elements)
    {
        uint32_t sequence_length = 0;
        state state_before_error(*this);

        deserialize(sequence_length);

        try
        {
            sequence_t = reinterpret_cast<_T*>(calloc(sequence_length, sizeof(_T)));
            deserialize_array(sequence_t, sequence_length);
        }
        catch (exception::Exception& ex)
        {
            free(sequence_t);
            sequence_t = NULL;
            set_state(state_before_error);
            ex.raise();
        }

        num_elements = sequence_length;
        return *this;
    }

    template<class _T>
    Cdr& deserialize_sequence(
            _T*& sequence_t,
            size_t& num_elements,
            Endianness endianness)
    {
        bool aux_swap = swap_bytes_;
        swap_bytes_ = (swap_bytes_ && (static_cast<Endianness>(endianness_) == endianness)) ||
                (!swap_bytes_ && (static_cast<Endianness>(endianness_) != endianness));

        try
        {
            deserialize_sequence(sequence_t, num_elements);
            swap_bytes_ = aux_swap;
        }
        catch (exception::Exception& ex)
        {
            swap_bytes_ = aux_swap;
            ex.raise();
        }

        return *this;
    }

    TEMPLATE_SPEC
    Cdr& deserialize_sequence(
            std::string*& sequence_t,
            size_t& num_elements)
    {
        return deserialize_string_sequence(sequence_t, num_elements);
    }

    TEMPLATE_SPEC
    Cdr& deserialize_sequence(
            std::wstring*& sequence_t,
            size_t& num_elements)
    {
        return deserialize_wstring_sequence(sequence_t, num_elements);
    }


    template<class _T>
    Cdr& serialize_member(
            const MemberId& member_id,
            const _T& member_value,
            XCdrHeaderSelection header_selection = XCdrHeaderSelection::AUTO_WITH_SHORT_HEADER_BY_DEFAULT)
    {
        Cdr::state current_state(*this);
        (this->*begin_serialize_member_)(member_id, true, current_state, header_selection);
        serialize(member_value);
        return (this->*end_serialize_member_)(current_state);
    }

    template<class _T>
    Cdr& serialize_member(
            const MemberId& member_id,
            const optional<_T>& member_value,
            XCdrHeaderSelection header_selection = XCdrHeaderSelection::AUTO_WITH_SHORT_HEADER_BY_DEFAULT)
    {
        Cdr::state current_state(*this);
        (this->*begin_serialize_opt_member_)(member_id, member_value.has_value(), current_state, header_selection);
        serialize(member_value);
        return (this->*end_serialize_opt_member_)(current_state);
    }

    template<class _T>
    Cdr& deserialize_member(
            _T& member_value)
    {
        return deserialize(member_value);
    }

    template<class _T>
    Cdr& deserialize_member(
            optional<_T>& member_value)
    {
        if (EncodingAlgorithmFlag::PLAIN_CDR == current_encoding_)
        {
            Cdr::state current_state(*this);
            MemberId member_id;
            xcdr1_deserialize_member_header(member_id, current_state);
            auto prev_offset = offset_;
            if (0 < current_state.member_size_)
            {
                deserialize(member_value);
            }
            if (current_state.member_size_ != offset_ - prev_offset)
            {
                throw exception::BadParamException(
                          "Member size provided by member header is not equal to the real decoded member size");
            }
        }
        else
        {
            deserialize(member_value);
        }
        return *this;
    }

    Cdr_DllAPI Cdr& begin_serialize_type(
            Cdr::state& current_state,
            EncodingAlgorithmFlag type_encoding);

    Cdr_DllAPI Cdr& end_serialize_type(
            Cdr::state& current_state);

    Cdr_DllAPI Cdr& deserialize_type(
            EncodingAlgorithmFlag type_encoding,
            std::function<bool (Cdr&, const MemberId&)> functor);

    template<class _T>
    Cdr& serialize(
            const optional<_T>& value)
    {
        if (CdrVersion::XCDRv2 == cdr_version_ && EncodingAlgorithmFlag::PL_CDR2 != current_encoding_)
        {
            serialize(value.has_value());
        }

        if (value.has_value())
        {
            serialize(*value);
        }
        return *this;
    }

    template<class _T>
    Cdr& serialize(
            const external<_T>& value)
    {
        if (!value)
        {
            throw exception::BadParamException("External member is null");
        }

        serialize(*value);
        return *this;
    }

    Cdr_DllAPI Cdr& operator <<(
            const MemberId& member_id);

    template<class _T>
    Cdr& deserialize(
            optional<_T>& value)
    {
        bool is_present = true;
        if (CdrVersion::XCDRv2 == cdr_version_ && EncodingAlgorithmFlag::PL_CDR2 != current_encoding_)
        {
            deserialize(is_present);
        }
        value.reset(is_present);
        if (is_present)
        {
            deserialize(*value);
        }
        return *this;
    }

    template<class _T>
    Cdr& deserialize(
            external<_T>& value)
    {
        if (value.is_locked())
        {
            throw exception::BadParamException("External member is locked");
        }

        if (!value)
        {
            value = external<_T>{new typename external<_T>::type()};
        }

        deserialize(*value);
        return *this;
    }

    template<class _T>
    Cdr& deserialize(
            optional<external<_T>>& value)
    {
        if (value.has_value() && value.value().is_locked())
        {
            throw exception::BadParamException("External member is locked");
        }

        bool is_present = true;
        if (CdrVersion::XCDRv2 == cdr_version_ && EncodingAlgorithmFlag::PL_CDR2 != current_encoding_)
        {
            deserialize(is_present);
        }
        value.reset(is_present);
        if (is_present)
        {
            deserialize(*value);
        }
        return *this;
    }

    Cdr_DllAPI state allocate_xcdrv2_dheader();

    Cdr_DllAPI void set_xcdrv2_dheader(
            const state& state);

private:

    Cdr(
            const Cdr&) = delete;

    Cdr& operator =(
            const Cdr&) = delete;

    Cdr_DllAPI Cdr& serialize_bool_array(
            const std::vector<bool>& vector_t);

    Cdr_DllAPI Cdr& serialize_bool_sequence(
            const std::vector<bool>& vector_t);

    Cdr_DllAPI Cdr& deserialize_bool_array(
            std::vector<bool>& vector_t);

    Cdr_DllAPI Cdr& deserialize_bool_sequence(
            std::vector<bool>& vector_t);

    Cdr_DllAPI Cdr& deserialize_string_sequence(
            std::string*& sequence_t,
            size_t& num_elements);

    Cdr_DllAPI Cdr& deserialize_wstring_sequence(
            std::wstring*& sequence_t,
            size_t& num_elements);

    template<class _T, size_t _Size>
    Cdr& serialize_array(
            const std::array<_T, _Size>* array_t,
            size_t num_elements)
    {
        return serialize_array(array_t->data(), num_elements * array_t->size());
    }

    template<class _T, size_t _Size>
    Cdr& deserialize_array(
            std::array<_T, _Size>* array_t,
            size_t num_elements)
    {
        return deserialize_array(array_t->data(), num_elements * array_t->size());
    }

    template<class _T, size_t _Size>
    Cdr& deserialize_array(
            std::array<_T, _Size>* array_t,
            size_t num_elements,
            Endianness endianness)
    {
        return deserialize_array(array_t->data(), num_elements * array_t->size(), endianness);
    }

    inline size_t alignment(
            size_t data_size) const
    {
        return data_size > last_data_size_ ? (data_size - ((offset_ - origin_) % data_size)) & (data_size - 1) : 0;
    }

    inline void make_alignment(
            size_t align)
    {
        offset_ += align;
        last_data_size_ = 0;
    }

    bool resize(
            size_t min_size_inc);

    Cdr_DllAPI const char* read_string(
            uint32_t& length);
    Cdr_DllAPI const std::wstring read_wstring(
            uint32_t& length);


    void xcdr1_serialize_short_member_header(
            const MemberId& member_id);

    void xcdr1_end_short_member_header(
            const MemberId& member_id,
            size_t member_serialized_size);

    void xcdr1_serialize_long_member_header(
            const MemberId& member_id);

    void xcdr1_end_long_member_header(
            const MemberId& member_id,
            size_t member_serialized_size);

    void xcdr1_change_to_short_member_header(
            const MemberId& member_id,
            size_t member_serialized_size);

    void xcdr1_change_to_long_member_header(
            const MemberId& member_id,
            size_t member_serialized_size);

    Cdr_DllAPI bool xcdr1_deserialize_member_header(
            MemberId& member_id,
            Cdr::state& current_state);

    void xcdr2_serialize_short_member_header(
            const MemberId& member_id);

    void xcdr2_end_short_member_header(
            const MemberId& member_id,
            size_t member_serialized_size);

    void xcdr2_serialize_long_member_header(
            const MemberId& member_id);

    void xcdr2_end_long_member_header(
            const MemberId& member_id,
            size_t member_serialized_size);

    void xcdr2_change_to_short_member_header(
            const MemberId& member_id,
            size_t member_serialized_size);

    void xcdr2_change_to_long_member_header(
            const MemberId& member_id,
            size_t member_serialized_size);

    void xcdr2_shrink_to_long_member_header(
            const MemberId& member_id,
            const FastBuffer::iterator& offset);

    void xcdr2_deserialize_member_header(
            MemberId& member_id,
            Cdr::state& current_state);

    Cdr& xcdr1_begin_serialize_member(
            const MemberId& member_id,
            bool is_present,
            Cdr::state& current_state,
            XCdrHeaderSelection header_selection);

    Cdr& xcdr1_end_serialize_member(
            const Cdr::state& current_state);

    Cdr& xcdr1_begin_serialize_opt_member(
            const MemberId& member_id,
            bool is_present,
            Cdr::state& current_state,
            XCdrHeaderSelection header_selection);

    Cdr& xcdr1_end_serialize_opt_member(
            const Cdr::state& current_state);

    Cdr& xcdr2_begin_serialize_member(
            const MemberId& member_id,
            bool is_present,
            Cdr::state& current_state,
            XCdrHeaderSelection header_selection);

    Cdr& xcdr2_end_serialize_member(
            const Cdr::state& current_state);

    Cdr& xcdr1_begin_serialize_type(
            Cdr::state& current_state,
            EncodingAlgorithmFlag type_encoding) noexcept;

    Cdr& xcdr1_end_serialize_type(
            const Cdr::state& current_state);

    Cdr& xcdr2_begin_serialize_type(
            Cdr::state& current_state,
            EncodingAlgorithmFlag type_encoding);

    Cdr& xcdr2_end_serialize_type(
            const Cdr::state& current_state);

    Cdr& xcdr1_deserialize_type(
            EncodingAlgorithmFlag type_encoding,
            std::function<bool (Cdr&, const MemberId&)> functor);

    Cdr& xcdr2_deserialize_type(
            EncodingAlgorithmFlag type_encoding,
            std::function<bool (Cdr&, const MemberId&)> functor);

    Cdr& cdr_begin_serialize_member(
            const MemberId& member_id,
            bool is_present,
            Cdr::state& current_state,
            XCdrHeaderSelection header_selection);

    Cdr& cdr_end_serialize_member(
            const Cdr::state& current_state);

    Cdr& cdr_begin_serialize_type(
            Cdr::state& current_state,
            EncodingAlgorithmFlag type_encoding);

    Cdr& cdr_end_serialize_type(
            const Cdr::state& current_state);

    Cdr& cdr_deserialize_type(
            EncodingAlgorithmFlag type_encoding,
            std::function<bool (Cdr&, const MemberId&)> functor);

    void reset_callbacks();

    using begin_serialize_member_functor = Cdr& (Cdr::*)(
        const MemberId&,
        bool,
        Cdr::state&,
        XCdrHeaderSelection);
    begin_serialize_member_functor begin_serialize_member_ { nullptr };

    using end_serialize_member_functor = Cdr& (Cdr::*)(
        const Cdr::state&);
    end_serialize_member_functor end_serialize_member_ { nullptr };

    using begin_serialize_opt_member_functor = Cdr& (Cdr::*)(
        const MemberId&,
        bool,
        Cdr::state&,
        XCdrHeaderSelection);
    begin_serialize_opt_member_functor begin_serialize_opt_member_ { nullptr };

    using end_serialize_memberopt__functor = Cdr& (Cdr::*)(
        const Cdr::state&);
    end_serialize_member_functor end_serialize_opt_member_ { nullptr };

    using begin_serialize_type_functor = Cdr& (Cdr::*)(
        Cdr::state&,
        EncodingAlgorithmFlag);
    begin_serialize_type_functor begin_serialize_type_ { nullptr };

    using end_serialize_type_functor = Cdr& (Cdr::*)(
        const Cdr::state&);
    end_serialize_type_functor end_serialize_type_ { nullptr };

    using deserialize_type_functor = Cdr& (Cdr::*)(
        EncodingAlgorithmFlag,
        std::function<bool (Cdr&, const MemberId&)>);
    deserialize_type_functor deserialize_type_ { nullptr };

    FastBuffer& cdr_buffer_;

    CdrVersion cdr_version_ {CdrVersion::XCDRv2};

    EncodingAlgorithmFlag encoding_flag_ {EncodingAlgorithmFlag::PLAIN_CDR2};

    EncodingAlgorithmFlag current_encoding_ {EncodingAlgorithmFlag::PLAIN_CDR2};

    std::array<uint8_t, 2> options_{{0}};

    uint8_t endianness_ {Endianness::LITTLE_ENDIANNESS};

    bool swap_bytes_ {false};

    size_t last_data_size_ {0};

    FastBuffer::iterator offset_;

    FastBuffer::iterator origin_;

    FastBuffer::iterator end_;

    MemberId next_member_id_;

    size_t align64_ {4};

    enum SerializedMemberSizeForNextInt
    {
        NO_SERIALIZED_MEMBER_SIZE,
        SERIALIZED_MEMBER_SIZE,
        SERIALIZED_MEMBER_SIZE_4,
        SERIALIZED_MEMBER_SIZE_8
    }
    serialized_member_size_ {NO_SERIALIZED_MEMBER_SIZE};

    state initial_state_;

    bool encapsulation_serialized_ {false};


    uint32_t get_long_lc(
            SerializedMemberSizeForNextInt serialized_member_size);

    uint32_t get_short_lc(
            size_t member_serialized_size);

    template<class _T, typename std::enable_if<std::is_enum<_T>::value ||
            std::is_arithmetic<_T>::value>::type* = nullptr>
    constexpr SerializedMemberSizeForNextInt get_serialized_member_size() const
    {
        return (1 == sizeof(_T) ? SERIALIZED_MEMBER_SIZE :
               (4 == sizeof(_T) ? SERIALIZED_MEMBER_SIZE_4 :
               (8 == sizeof(_T) ? SERIALIZED_MEMBER_SIZE_8 :  NO_SERIALIZED_MEMBER_SIZE)));
    }

};

}            //namespace fastcdr
}        //namespace eprosima

#endif // _CDR_CDR_H_