buffer_input_archive.hpp 4.04 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_INPUT_ARCHIVE_HPP
#define __THALLIUM_BUFFER_INPUT_ARCHIVE_HPP

Matthieu Dorier's avatar
Matthieu Dorier committed
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
#include <thallium/config.hpp>

#ifdef THALLIUM_USE_CEREAL

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

namespace thallium {

    using buffer_input_archive = cereal_input_archive;

}


#else

24 25 26 27 28 29 30 31
#include <type_traits>
#include <stdexcept>
#include <cstring>
#include <thallium/serialization/serialize.hpp>
#include <thallium/buffer.hpp>

namespace thallium {

Matthieu Dorier's avatar
Matthieu Dorier committed
32 33
class engine;

34 35 36 37 38 39 40 41 42 43 44
/**
 * buffer_input_archive wraps a buffer object and
 * offers the functionalities to deserialize its content
 * into C++ objects. It inherits from the input_archive
 * trait so that serialization methods know they have to
 * take data out of the buffer and into C++ objects.
 */
class buffer_input_archive : public input_archive {

private:

45 46
    const buffer& m_buffer;
    std::size_t   m_pos;
Matthieu Dorier's avatar
Matthieu Dorier committed
47
    engine*       m_engine;
48

49 50 51 52
    template<typename T, bool b>
    inline void read_impl(T&& t, const std::integral_constant<bool, b>&) {
        load(*this,std::forward<T>(t));
    }
53

54 55 56 57
    template<typename T>
    inline void read_impl(T&& t, const std::true_type&) {
        read(&t);
    }
58 59 60

public:

61 62 63 64 65 66 67 68 69
    /**
     * Constructor.
     *
     * \param b : reference to a buffer from which to read.
     * \warning The buffer is held by reference so the life span of
     * the buffer_input_archive instance should be shorter than that
     * of the buffer.
     */
    buffer_input_archive(const buffer& b, engine& e)
Matthieu Dorier's avatar
Matthieu Dorier committed
70 71 72 73
    : m_buffer(b), m_pos(0), m_engine(&e) {}

    buffer_input_archive(const buffer& b)
    : m_buffer(b), m_pos(0), m_engine(nullptr) {}
74

75 76 77
    /**
     * Operator to get C++ objects of type T from the archive.
     * The object should either be a basic type, or an STL container
Matthieu Dorier's avatar
Matthieu Dorier committed
78 79 80
     * (in which case the appropriate thallium/serialization/stl/ header
     * should be included for this function to be properly instanciated),
     * or any object for which either a serialize member function or
81 82 83
     * a load member function has been provided.
     */
    template<typename T>
Matthieu Dorier's avatar
Matthieu Dorier committed
84
    inline buffer_input_archive& operator&(T&& obj) {
85 86 87 88
        read_impl(std::forward<T>(obj), std::is_arithmetic<typename std::decay<T>::type>());
        return *this;
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
    /**
     * @brief Parenthesis operator with one argument, equivalent to & operator.
     */
    template<typename T>
    inline buffer_input_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_input_archive& operator()(T&& obj, Targs&&... others) {
        (*this) & std::forward<T>(obj);
        return (*this)(std::forward<Targs>(others)...);
    }

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

    /**
     * Basic function to read count objects of type T from the buffer.
     * A memcopy is performed from the buffer to the object, so the
     * object should either be a basic type or an object that can be
     * memcopied instead of calling a more elaborate serialize function.
     */
    template<typename T>
    inline void read(T* t, std::size_t count=1) {
        if(m_pos + count*sizeof(T) > m_buffer.size()) {
            throw std::runtime_error("Reading beyond buffer size");
        }
        std::memcpy((void*)t,(const void*)(m_buffer.data() + m_pos),count*sizeof(T));
        m_pos += count*sizeof(T);
    }
Matthieu Dorier's avatar
Matthieu Dorier committed
130

131 132 133 134 135 136 137 138 139 140 141 142 143
    /**
     * @brief Equivalent to read().
     */
    template<typename T>
    inline void copy(T* t, std::size_t count=1) {
        read(t, count);
    }

    /**
     * @brief Returns the engine registered in the archive.
     *
     * @return The engine registered in the archive.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
144 145 146
    engine& get_engine() const {
        return *m_engine;
    }
147 148 149 150
};

}
#endif
Matthieu Dorier's avatar
Matthieu Dorier committed
151
#endif