Encode Fix messages with boost::fusion


#include <boost/fusion/container/set.hpp>
#include <boost/fusion/include/at_key.hpp>
#include <boost/fusion/include/fold.hpp>
#include <cstring>
#include <iostream>

struct Tag1
{
    char value;

    void set(char v)
    {
        value = v;
    }

    int print(char* buf, std::size_t size) const
    {
        return std::snprintf(buf, size, "35=%c", value);
    }
};

struct Tag2
{
    int value;

    void set(int v)
    {
        value = v;
    }

    int print(char* buf, std::size_t size) const
    {
        return std::snprintf(buf, size, "\00121=%d", value);
    }
};

struct Tag3
{
    char value[32];

    void set(const char* v)
    {
        std::strncpy(value, v, sizeof(value));
        value[sizeof(value) - 1] = 0;
    }

    int print(char* buf, std::size_t size) const
    {
        return std::snprintf(buf, size, "\00155=%s", value);
    }
};

struct Writer
{
private:
    struct Func
    {
        Func(char* data, int capacity) : m_data(data), m_capacity(capacity) {}

        template <typename T>
        int operator()(int size, const T& data) const
        {
            if (m_capacity < size)
            {
                return -1;
            }

            int res = data.print(m_data + size, static_cast<std::size_t>(m_capacity - size));
            if (res < 0)
            {
                return res;
            }

            return size + res;
        }
    private:
        char* m_data;
        int m_capacity;
    };

public:
    template<typename T>
    int operator()(const T& msg, char* buffer, int capacity)
    {
        Func func{buffer, capacity};
        return boost::fusion::fold(msg, 0, func);
    }
};

int main()
{
    using Msg = boost::fusion::set<Tag1, Tag3, Tag2>;

    Msg msg;
    boost::fusion::at_key<Tag1>(msg).set('A');
    boost::fusion::at_key<Tag2>(msg).set(123);
    boost::fusion::at_key<Tag3>(msg).set("AAPL");

    char buf[109];
    int size = Writer()(msg, buf, sizeof(buf));
    if (size > 0)
        std::cout << std::string(buf, static_cast<std::size_t>(size)) << std::endl;
}

Advertisements
This entry was posted in Programming. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s