So I've made custom binary streams which work like this:
/// \brief Reads a variable from the stream.
/// \tparam T Type of the variable.
/// \param[out] var Variable to read.
/// \return Reference to this stream.
/// \throw TODO
/// \note No endianness conversion will be performed if a byte is not 8 bit
/// wide.
template <typename T>
BinaryInputStream& operator>>(T& var)
{
static_assert(std::is_pod<T>::value, "BinaryInputStream::operator>>: "
"Binary stream can only read POD types.");
static_assert(!std::is_enum<T>::value, "BinaryInputStream::operator>>: "
"Directly reading enums is unsafe. Implement a custom overload and "
"check the value inside it.");
char* buffer = reinterpret_cast<char*>(&var);
std::size_t buffersize = sizeof(var);
this->Read(buffer, buffersize);
#if CHAR_BIT == 8
Endianness systemendianness = General::GetEndianness();
if (systemendianness == Endianness::Unknown)
{
return *this;
}
if (systemendianness != this->GetEndianness())
{
SwapBytes(var);
}
#endif
return *this;
}
/// \brief Writes a variable to the stream.
/// \tparam T Type of the variable.
/// \param[in] var Variable to write.
/// \return Reference to this stream.
/// \throw TODO
/// \note No endianness conversion will be performed if a byte is not 8 bit
/// wide.
template <typename T>
BinaryOutputStream& operator<<(T var)
{
static_assert(std::is_pod<T>::value,
"Binary stream can only write POD types.");
#if CHAR_BIT == 8
Endianness systemendianness = General::GetEndianness();
if ((systemendianness != Endianness::Unknown) &&
(systemendianness != this->GetEndianness()))
{
SwapBytes(var);
}
#endif
char* buffer = reinterpret_cast<char*>(&var);
std::size_t buffersize = sizeof(var);
this->Write(buffer, buffersize);
return *this;
}
/// \brief Swaps bytes of a given variable.
/// \tparam T type of the variable.
/// \param[in,out] var Input variable.
template <typename T>
void SwapBytes(T &var)
{
char* buffer = reinterpret_cast<char*>(&var);
for (std::size_t i = 0, j = sizeof(var) - 1; i < j; ++i, --j)
{
std::swap(buffer[i], buffer[j]);
}
}
Is this correct? Have I triggered undefined behavior? Are static_asserts correct? Maybe they are overly restrictive or not strict enough? Please quote the standard if possible.
this
pointer correctly these are class method templates. Wouldn't it be better to provide rest of the class or at least relevant methods? \$\endgroup\$std::istream
andstd::ostream
functions. You can view the full source code here: gitlab.com/ftz/general \$\endgroup\$