Program Listing for File binary-serialization.h

Return to documentation for file (common/maplab-common/include/maplab-common/binary-serialization.h)

#ifndef MAPLAB_COMMON_BINARY_SERIALIZATION_H_
#define MAPLAB_COMMON_BINARY_SERIALIZATION_H_
#include <fstream>  // NOLINT
#include <limits>
#include <list>
#include <map>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>

#include <Eigen/Dense>
#include <aslam/common/hash-id.h>
#include <glog/logging.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <maplab-common/test/serialization-macros.h>

namespace sm {
class HashId;
}  // namespace sm

namespace common {
template <class TYPE>
void Serialize(
    const TYPE& value, std::ostream* out,
    typename std::enable_if<std::is_integral<TYPE>::value>::type* = 0) {
  CHECK_NOTNULL(out);
  out->write(reinterpret_cast<const char*>(&value), sizeof(value));
}

template <class TYPE>
void Deserialize(
    TYPE* value, std::istream* in,
    typename std::enable_if<std::is_integral<TYPE>::value>::type* = 0) {
  CHECK_NOTNULL(value);
  CHECK_NOTNULL(in);
  in->read(reinterpret_cast<char*>(value), sizeof(*value));
  CHECK_EQ(in->gcount(), static_cast<std::streamsize>(sizeof(*value)));
}

template <class TYPE>
void Serialize(
    const TYPE& value, std::ostream* out,
    typename std::enable_if<std::is_floating_point<TYPE>::value>::type* = 0) {
  CHECK_NOTNULL(out);
  out->write(reinterpret_cast<const char*>(&value), sizeof(value));
}

template <class TYPE>
void Deserialize(
    TYPE* value, std::istream* in,
    typename std::enable_if<std::is_floating_point<TYPE>::value>::type* = 0) {
  CHECK_NOTNULL(value);
  CHECK_NOTNULL(in);
  in->read(reinterpret_cast<char*>(value), sizeof(*value));
  CHECK_EQ(in->gcount(), static_cast<std::streamsize>(sizeof(*value)));
}

void Serialize(const uint32_t& value, std::ostream* out);

void Deserialize(uint32_t* value, std::istream* in);

void Serialize(const std::string& value, std::ostream* out);

void Deserialize(std::string* value, std::istream* in);

void Serialize(
    const char* memory_start, unsigned int memory_block_length_bytes,
    std::ostream* out);

void Deserialize(
    char* memory_start, unsigned int memory_block_length_bytes,
    std::istream* in);

void Serialize(
    const unsigned char* memory_start, unsigned int memory_block_length_bytes,
    std::ostream* out);

void Deserialize(
    unsigned char* memory_start, unsigned int memory_block_length_bytes,
    std::istream* in);

void Serialize(const aslam::HashId& value, std::ostream* out);

void Deserialize(aslam::HashId* value, std::istream* in);

template <typename TYPEA, typename TYPEB>
void Serialize(const std::pair<TYPEA, TYPEB>& value, std::ostream* out) {
  CHECK_NOTNULL(out);
  Serialize(value.first, out);
  Serialize(value.second, out);
}

template <typename TYPEA, typename TYPEB>
void Deserialize(std::pair<TYPEA, TYPEB>* value, std::istream* in) {
  CHECK_NOTNULL(value);
  CHECK_NOTNULL(in);
  Deserialize(&value->first, in);
  Deserialize(&value->second, in);
}

template <typename TYPEA, typename TYPEB>
void Serialize(const std::map<TYPEA, TYPEB>& value, std::ostream* out) {
  CHECK_NOTNULL(out);
  uint32_t length = value.size();
  Serialize(length, out);
  for (const std::pair<TYPEA, TYPEB>& entry : value) {
    Serialize(entry, out);
  }
}

template <typename TYPEA, typename TYPEB>
void Deserialize(std::map<TYPEA, TYPEB>* value, std::istream* in) {
  CHECK_NOTNULL(value);
  CHECK_NOTNULL(in);
  value->clear();
  uint32_t length;
  Deserialize(&length, in);
  for (uint32_t i = 0; i < length; ++i) {
    std::pair<TYPEA, TYPEB> entry;
    Deserialize(&entry, in);
    value->insert(entry);
  }
}

template <class Scalar, int Rows, int Cols, int C, int D, int E>
void Serialize(
    const Eigen::Matrix<Scalar, Rows, Cols, C, D, E>& M, std::ostream* out) {
  CHECK_NOTNULL(out);
  int rows = M.rows();
  int cols = M.cols();
  CHECK_NE(0, rows);
  CHECK_NE(0, cols);

  Serialize(rows, out);
  Serialize(cols, out);

  Serialize(
      reinterpret_cast<const char*>(M.data()), sizeof(Scalar) * rows * cols,
      out);
}

template <class Scalar, int Rows, int Cols, int C, int D, int E>
void Deserialize(
    Eigen::Matrix<Scalar, Rows, Cols, C, D, E>* M, std::istream* in) {
  CHECK_NOTNULL(M);
  CHECK_NOTNULL(in);
  int rows, cols;
  Deserialize(&rows, in);
  Deserialize(&cols, in);
  CHECK_NE(0, rows);
  CHECK_NE(0, cols);

  CHECK_EQ(rows, Rows) << "Unexpected number of rows for fixed-sized type.";
  CHECK_EQ(cols, Cols) << "Unexpected number of columns for fixed-sized type.";

  Deserialize(
      reinterpret_cast<char*>(M->data()), sizeof(Scalar) * rows * cols, in);
}

template <class Scalar, int Cols, int C, int D, int E>
void Deserialize(
    Eigen::Matrix<Scalar, Eigen::Dynamic, Cols, C, D, E>* M, std::istream* in) {
  CHECK_NOTNULL(M);
  CHECK_NOTNULL(in);
  int rows, cols;
  Deserialize(&rows, in);
  Deserialize(&cols, in);
  CHECK_NE(0, rows);
  CHECK_NE(0, cols);

  CHECK_EQ(cols, Cols) << "Unexpected number of columns for fixed-sized type.";
  M->resize(rows, Eigen::NoChange);

  Deserialize(
      reinterpret_cast<char*>(M->data()), sizeof(Scalar) * rows * cols, in);
}

template <class Scalar, int Rows, int C, int D, int E>
void Deserialize(
    Eigen::Matrix<Scalar, Rows, Eigen::Dynamic, C, D, E>* M, std::istream* in) {
  CHECK_NOTNULL(M);
  CHECK_NOTNULL(in);
  int rows, cols;
  Deserialize(&rows, in);
  Deserialize(&cols, in);
  CHECK_NE(0, rows);
  CHECK_NE(0, cols);

  CHECK_EQ(rows, Rows) << "Unexpected number of rows for fixed-sized type.";
  M->resize(Eigen::NoChange, cols);

  Deserialize(
      reinterpret_cast<char*>(M->data()), sizeof(Scalar) * rows * cols, in);
}

template <class Scalar, int C, int D, int E>
void Deserialize(
    Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, C, D, E>* M,
    std::istream* in) {
  CHECK_NOTNULL(M);
  CHECK_NOTNULL(in);
  int rows, cols;
  Deserialize(&rows, in);
  Deserialize(&cols, in);
  CHECK_NE(0, rows);
  CHECK_NE(0, cols);

  M->resize(rows, cols);

  Deserialize(
      reinterpret_cast<char*>(M->data()), sizeof(Scalar) * rows * cols, in);
}

template <template <typename, typename> class CONTAINER, typename TYPE,
          typename ALLOCATOR>
void Serialize(const CONTAINER<TYPE, ALLOCATOR>& value, std::ostream* out) {
  CHECK_NOTNULL(out);
  uint32_t length = value.size();
  Serialize(length, out);
  for (const TYPE& entry : value) {
    Serialize(entry, out);
  }
}

template <template <typename, typename> class CONTAINER, typename TYPE,
          typename ALLOCATOR>
void Deserialize(CONTAINER<TYPE, ALLOCATOR>* value, std::istream* in) {
  CHECK_NOTNULL(value);
  CHECK_NOTNULL(in);
  value->clear();
  uint32_t length;
  Deserialize(&length, in);
  value->resize(length);
  for (TYPE& entry : *value) {
    Deserialize(&entry, in);
  }
}

}  // namespace common

#endif  // MAPLAB_COMMON_BINARY_SERIALIZATION_H_