buffer_output_archive.hpp 3.98 KB
Newer Older
Matthieu Dorier's avatar
Matthieu Dorier committed
1 2 3 4 5
/*
 * (C) 2017 The University of Chicago
 * 
 * See COPYRIGHT in top-level directory.
 */
6 7 8
#ifndef __THALLIUM_BUFFER_OUTPUT_ARCHIVE_HPP
#define __THALLIUM_BUFFER_OUTPUT_ARCHIVE_HPP

9 10 11 12 13 14 15 16 17 18 19 20 21 22
#include <thallium/config.hpp>

#ifdef THALLIUM_USE_CEREAL

#include <thallium/serialization/cereal/archives.hpp>

namespace thallium {

        using buffer_output_archive = cereal_output_archive;

}

#else

23 24 25 26 27 28
#include <type_traits>
#include <thallium/serialization/serialize.hpp>
#include <thallium/buffer.hpp>

namespace thallium {

Matthieu Dorier's avatar
Matthieu Dorier committed
29 30
class engine;

31 32 33 34 35 36 37 38 39 40 41
/**
 * buffer_output_archive wraps and hg::buffer object and
 * offers the functionalities to serialize C++ objects into
 * the buffer. The buffer is resized down to 0 when creating
 * the archive and will be extended back to an appropriate size
 * as C++ objects are serialized into it.
 */
class buffer_output_archive : public output_archive {

private:

42 43
    buffer&     m_buffer;
    std::size_t m_pos;
Matthieu Dorier's avatar
Matthieu Dorier committed
44
    engine*     m_engine;
45

46 47 48 49
    template<typename T, bool b>
    inline void write_impl(T&& t, const std::integral_constant<bool, b>&) {
        save(*this,std::forward<T>(t));
    }
50

51 52 53 54
    template<typename T>
    inline void write_impl(T&& t, const std::true_type&) {
        write((char*)&t,sizeof(T));
    }
55 56 57

public:

58 59 60 61 62 63 64 65 66
    /**
     * Constructor.
     * 
     * \param b : reference to a buffer into which to write.
     * \warning The buffer is held by reference so the life span
     * of the buffer_output_archive instance should be shorter than
     * that of the buffer itself.
     */
    buffer_output_archive(buffer& b, engine& e)
Matthieu Dorier's avatar
Matthieu Dorier committed
67
    : m_buffer(b), m_pos(0), m_engine(&e) {
68 69
        m_buffer.resize(0);
    }
70

Matthieu Dorier's avatar
Matthieu Dorier committed
71 72 73 74 75
    buffer_output_archive(buffer& b)
    : m_buffer(b), m_pos(0), m_engine(nullptr) {
        m_buffer.resize(0);
    }

76 77 78 79 80 81 82 83 84
    /**
     * Operator to add a C++ object of type T into the archive.
     * The object should either be a basic type, or an STL container
     * (in which case the appropriate hgcxx/hg_stl/stl_* header should
     * be included for this function to be properly instanciated), or
     * any object for which either a serialize member function or
     * a load member function has been provided.
     */
    template<typename T>
85
    inline buffer_output_archive& operator&(T&& obj) {
86 87 88 89
        write_impl(std::forward<T>(obj), std::is_arithmetic<typename std::decay<T>::type>());
        return *this;
    }

90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
    /**
     * @brief Parenthesis operator with one argument, equivalent to & operator.
     */
    template<typename T>
    inline buffer_output_archive& operator()(T&& obj) {
        return (*this) & std::forward<T>(obj);
    }

    /**
     * @brief Parenthesis operator with multiple arguments.
     * ar(x,y,z) is equivalent to ar & x & y & z.
     */
    template<typename T, typename ... Targs>
    inline buffer_output_archive& operator()(T&& obj, Targs&&... others) {
        (*this) & std::forward<T>(obj);
        return (*this)(std::forward<Targs>(others)...);
    }

108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
    /**
     * Operator << is equivalent to operator &.
     * \see operator&
     */
    template<typename T>
    buffer_output_archive& operator<<(T&& obj) {
        return (*this) & std::forward<T>(obj);
    }

    /**
     * Basic function to write count objects of type T into the buffer.
     * A memcopy is performed from the object's address to the buffer, so
     * the object should either be basic type or an object that can be
     * memcopied instead of calling a more elaborate serialize function.
     */
    template<typename T>
    inline void write(T* const t, size_t count=1) {
        size_t s = count*sizeof(T);
        if(m_pos+s > m_buffer.size()) {
            if(m_pos+s > m_buffer.capacity()) {
                m_buffer.reserve(m_buffer.capacity()*2);
            }
            m_buffer.resize(m_pos+s);
        }
        memcpy((void*)(m_buffer.data() + m_pos),(void*)t,s);
        m_pos += s;
    }
135 136 137 138 139 140 141 142

    /**
     * @brief Equivalent to write().
     */
    template<typename T>
    inline void copy(T* const t, size_t count=1) {
        write(t, count);
    }
143 144 145 146 147
};

}

#endif
148
#endif