Skip to content

Commit

Permalink
containers: add binary stream operators for containers of the standar…
Browse files Browse the repository at this point in the history
…d library
  • Loading branch information
andrea-iob committed Feb 29, 2024
1 parent 0bd7f5f commit 3533579
Show file tree
Hide file tree
Showing 5 changed files with 555 additions and 27 deletions.
1 change: 1 addition & 0 deletions src/containers/binary_stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <cassert>
#include <limits>
#include <cmath>
#include <cstring>

#include "binary_stream.hpp"

Expand Down
45 changes: 34 additions & 11 deletions src/containers/binary_stream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,57 @@
#ifndef __BITPIT_BINARY_STREAM_HPP__
#define __BITPIT_BINARY_STREAM_HPP__

#include <vector>
#include <string>
#include <fstream>
#include <cstring>
#include <array>
#include <iostream>
#include <stdexcept>
#include <map>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

namespace bitpit {

// Stream operators
class IBinaryStream;
class OBinaryStream;

template<typename T>
IBinaryStream & operator>>(IBinaryStream &stream, T &data);
template<typename T, std::size_t d>
IBinaryStream &operator>>(IBinaryStream &stream, std::array<T, d> &data);
template<typename T, std::size_t d>
OBinaryStream &operator<<(OBinaryStream &stream, const std::array<T, d> &data);

template<typename T>
IBinaryStream& operator>>(IBinaryStream &stream, std::vector<T> &data);
template<typename T>
OBinaryStream& operator<<(OBinaryStream &stream, const std::vector<T> &data);

template<>
IBinaryStream & operator>>(IBinaryStream &stream, std::string &data);
template<typename K, typename T>
IBinaryStream &operator>>(IBinaryStream &stream, std::pair<K, T> &data);
template<typename K, typename T>
OBinaryStream &operator<<(OBinaryStream &stream, const std::pair<K, T> &data);

template<typename K, typename T>
IBinaryStream &operator>>(IBinaryStream &stream, std::map<K, T> &data);
template<typename K, typename T>
OBinaryStream &operator<<(OBinaryStream &stream, const std::map<K, T> &data);

template<typename K, typename T>
IBinaryStream &operator>>(IBinaryStream &stream, std::unordered_map<K, T> &data);
template<typename K, typename T>
OBinaryStream &operator<<(OBinaryStream &stream, const std::unordered_map<K, T> &data);

template<typename T>
OBinaryStream & operator<<(OBinaryStream &stream, const T &data);
IBinaryStream &operator>>(IBinaryStream &stream, std::unordered_set<T> &data);
template<typename T>
OBinaryStream &operator<<(OBinaryStream &stream, const std::unordered_set<T> &data);

template<typename T>
OBinaryStream& operator<<(OBinaryStream &stream, const std::vector<T> &data);
IBinaryStream & operator>>(IBinaryStream &stream, T &data);
template<typename T>
OBinaryStream & operator<<(OBinaryStream &stream, const T &data);

template<>
IBinaryStream & operator>>(IBinaryStream &stream, std::string &data);
template<>
OBinaryStream & operator<<(OBinaryStream &stream, const std::string &data);

Expand Down
261 changes: 245 additions & 16 deletions src/containers/binary_stream.tpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,35 @@
namespace bitpit {

/*!
* Read the specified value from the stream.
* Read the specified array from the stream.
*
* \param[in] stream is the input stream
* \param[in] data is the data to be streamed
* \result Returns the updated input stream.
* \result Returns the same input stream received in input.
*/
template<typename T>
IBinaryStream& operator>>(IBinaryStream &stream, T &data)
template<typename T, std::size_t SIZE>
IBinaryStream & operator>>(IBinaryStream &stream, std::array<T, SIZE> &data)
{
stream.read(reinterpret_cast<char *>(&data), sizeof(T));
for (T &value : data) {
stream >> value;
}

return stream;
}

/*!
* Write the specified array into the stream.
*
* \param[in] stream is the output stream
* \param[in] data is the data to be streamed
* \result Returns the same output stream received in input.
*/
template<typename T, std::size_t SIZE>
OBinaryStream & operator<<(OBinaryStream &stream, const std::array<T, SIZE> &data)
{
for (const T &value : data) {
stream << value;
}

return stream;
}
Expand All @@ -50,48 +69,258 @@ IBinaryStream& operator>>(IBinaryStream &stream, T &data)
* \result Returns the updated input stream.
*/
template<typename T>
IBinaryStream& operator>>(IBinaryStream &stream, std::vector<T> &data)
IBinaryStream & operator>>(IBinaryStream &stream, std::vector<T> &data)
{
std::size_t size;
stream.read(reinterpret_cast<char *>(&size), sizeof(size));
data.resize(size);

stream.read(reinterpret_cast<char *>(data.data()), size * sizeof(T));
for (T &value : data) {
stream >> value;
}

return stream;
}

/*!
* Write the specified value into the stream.
* Write the specified vector into the stream.
*
* Along with vector data, also the size of the vector is stored into the
* stream.
*
* \param[in] stream is the output stream
* \param[in] data is the data to be streamed
* \param[in] data is the vector to be streamed
* \result Returns the updated output stream.
*/
template<typename T>
OBinaryStream& operator<<(OBinaryStream &stream, const T &data)
OBinaryStream & operator<<(OBinaryStream &stream, const std::vector<T> &data)
{
stream.write(reinterpret_cast<const char *>(&data), sizeof(T));
std::size_t size = data.size();
stream.write(reinterpret_cast<const char *>(&size), sizeof(size));

for (const T &value : data) {
stream << value;
}

return stream;
}

/*!
* Write the specified vector into the stream.
* Read the specified pair from the stream.
*
* Along with vector data, also the size of the vector is stored into the
* \param[in] stream is the input stream
* \param[in] data is the pair to be streamed
* \result Returns the same input stream received in input.
*/
template<typename T1, typename T2>
IBinaryStream & operator>>(IBinaryStream &stream, std::pair<T1, T2> &data)
{
T1 first;
T2 second;
stream >> first;
stream >> second;
data = std::make_pair(std::move(first), std::move(second));

return stream;
}

/*!
* Write the specified pair into the stream.
*
* \param[in] stream is the input stream
* \param[in] data is the data to be streamed
* \result Returns the same input stream received in input.
*/
template<typename T1, typename T2>
OBinaryStream & operator<<(OBinaryStream &stream, const std::pair<T1, T2> &data)
{
stream << data.first;
stream << data.second;

return stream;
}

/*!
* Read the specified map from the stream.
*
* Input map will be clear and its contents will be replaced with the ones stored into
* the stream.
*
* \param[in] stream is the input stream
* \param[in] data is the data to be streamed
* \result Returns the same input stream received in input.
*/
template<typename K, typename T>
IBinaryStream & operator>>(IBinaryStream &stream, std::unordered_map<K, T> &data)
{
std::size_t size;
stream.read(reinterpret_cast<char *>(&size), sizeof(size));

data.clear();
data.reserve(size);
for (std::size_t i = 0; i < size; ++i) {
K key;
T value;
stream >> key;
stream >> value;
data[key] = std::move(value);
}

return stream;
}

/*!
* Write the specified map into the stream.
*
* Along with map data, also the size of the map is stored into the
* stream.
*
* \param[in] stream is the output stream
* \param[in] data is the data to be streamed
* \result Returns the updated output stream.
* \result Returns the same output stream received in input.
*/
template<typename K, typename T>
OBinaryStream & operator<<(OBinaryStream &stream, const std::unordered_map<K, T> &data)
{
std::size_t size = data.size();
stream.write(reinterpret_cast<const char *>(&size), sizeof(size));

for (const auto &entry : data) {
stream << entry.first;
stream << entry.second;
}

return stream;
}

/*!
* Read the specified map from the stream.
*
* Input map will be clear and its contents will be replaced with the ones stored into
* the stream.
*
* \param[in] stream is the input stream
* \param[in] data is the data to be streamed
* \result Returns the same input stream received in input.
*/
template<typename K, typename T>
IBinaryStream & operator>>(IBinaryStream &stream, std::map<K, T> &data)
{
std::size_t size;
stream.read(reinterpret_cast<char *>(&size), sizeof(size));

data.clear();
for (std::size_t i = 0; i < size; ++i) {
K key;
T value;
stream >> key;
stream >> value;
data[key] = std::move(value);
}

return stream;
}

/*!
* Write the specified map into the stream.
*
* Along with map data, also the size of the map is stored into the
* stream.
*
* \param[in] stream is the output stream
* \param[in] data is the data to be streamed
* \result Returns the same output stream received in input.
*/
template<typename K, typename T>
OBinaryStream & operator<<(OBinaryStream &stream, const std::map<K, T> &data)
{
std::size_t size = data.size();
stream.write(reinterpret_cast<const char *>(&size), sizeof(size));

for (const auto &entry : data) {
stream << entry.first;
stream << entry.second;
}

return stream;
}

/*!
* Read the specified set from the stream.
*
* Input set will be clear and its contents will be replaced with the ones stored into
* the stream.
*
* \param[in] stream is the input stream
* \param[in] data is the data to be streamed
* \result Returns the same input stream received in input.
*/
template<typename T>
OBinaryStream& operator<<(OBinaryStream &stream, const std::vector<T> &data)
IBinaryStream & operator>>(IBinaryStream &stream, std::unordered_set<T> &data)
{
std::size_t size;
stream.read(reinterpret_cast<char *>(&size), sizeof(size));

data.clear();
data.reserve(size);
for (std::size_t i = 0; i < size; ++i) {
T value;
stream >> value;
data.insert(std::move(value));
}

return stream;
}

/*!
* Write the specified set into the stream.
*
* Along with set data, also the size of the map is stored into the
* stream.
*
* \param[in] stream is the output stream
* \param[in] data is the data to be streamed
* \result Returns the same output stream received in input.
*/
template<typename T>
OBinaryStream & operator<<(OBinaryStream &stream, const std::unordered_set<T> &data)
{
std::size_t size = data.size();
stream.write(reinterpret_cast<const char *>(&size), sizeof(size));

stream.write(reinterpret_cast<const char *>(data.data()), size * sizeof(T));
for (const auto &value : data) {
stream << value;
}

return stream;
}

/*!
* Read the specified value from the stream.
*
* \param[in] stream is the input stream
* \param[in] data is the value to be streamed
* \result Returns the updated input stream.
*/
template<typename T>
IBinaryStream & operator>>(IBinaryStream &stream, T &data)
{
stream.read(reinterpret_cast<char *>(&data), sizeof(T));

return stream;
}

/*!
* Write the specified value into the stream.
*
* \param[in] stream is the output stream
* \param[in] data is the data to be streamed
* \result Returns the updated output stream.
*/
template<typename T>
OBinaryStream & operator<<(OBinaryStream &stream, const T &data)
{
stream.write(reinterpret_cast<const char *>(&data), sizeof(T));

return stream;
}
Expand Down
Loading

0 comments on commit 3533579

Please sign in to comment.