|
- #pragma once
-
- #include <cppcore/conversion/convert_cast.h>
-
- #include "stream.h"
-
- namespace cppcore
- {
-
- /* stream_helper_t */
-
- template<typename T_traits>
- template<class T>
- size_t stream_helper_t<T_traits>
- ::write(std::ostream& os, const T& t)
- { return __impl::op_stream_write<T>()(os, t); }
-
- template<typename T_traits>
- template<class T>
- size_t stream_helper_t<T_traits>
- ::read(std::istream& is, T& t)
- { return __impl::op_stream_read<T>()(is, t); }
-
- template<typename T_traits>
- template<class T>
- T stream_helper_t<T_traits>
- ::read(std::istream& is)
- {
- T t;
- read<T>(is, t);
- return std::move(t);
- }
-
- /* stream_writer_t */
-
- template<typename T_traits>
- stream_writer_t<T_traits>
- ::stream_writer_t(std::ostream& p_stream)
- : stream(p_stream)
- { }
-
- template<typename T_traits>
- template<class T>
- void stream_writer_t<T_traits>
- ::write(const T& t)
- { stream_helper_type::template write<T>(stream, t); }
-
- /* stream_reader_t */
-
- template<typename T_traits>
- stream_reader_t<T_traits>
- ::stream_reader_t(std::istream& p_stream)
- : stream(p_stream)
- { }
-
- template<typename T_traits>
- template<class T>
- size_t stream_reader_t<T_traits>
- ::read(T& t)
- { return stream_helper_type::template read<T>(stream, t); }
-
- template<typename T_traits>
- template<class T>
- T stream_reader_t<T_traits>
- ::read(std::istream& is)
- { return stream_helper_type::template read<T>(stream); }
-
- /* stream_format_saver */
-
- inline stream_format_saver
- ::stream_format_saver(std::ostream& s)
- : stream(s)
- { copyfmt(stream); }
-
- inline stream_format_saver
- ::~stream_format_saver()
- { stream.copyfmt(*this); }
-
- namespace __impl
- {
-
- /* op_stream_read */
-
- template<class T, class Enable>
- struct op_stream_read
- {
- inline size_t operator()(std::istream& is, T& t)
- {
- if (!is)
- throw exception("unable to read data from stream: invalid stream");
- if (is.read(reinterpret_cast<char*>(&t), sizeof(t)).gcount() != sizeof(t))
- throw exception("unable to read data from stream: EOF");
- if (!is)
- throw exception("unable to read data from stream: stream error");
- return sizeof(t);
- }
- };
-
- template<>
- struct op_stream_read<std::string, void>
- {
- inline size_t operator()(std::istream& is, std::string& t)
- {
- uint32_t sz;
- op_stream_read<uint32_t, void>()(is, sz);
- if (!is)
- throw exception("unable to read data from stream: invalid stream");
-
- std::string tmp;
- tmp.resize(sz);
- if (is.read(const_cast<char*>(tmp.data()), sz).gcount() != sz)
- throw exception("unable to read data from stream: EOF");
- if (!is)
- throw exception("unable to read data from stream: stream error");
- t = std::move(tmp);
-
- return sizeof(sz) + sz;
- }
- };
-
- template<class T>
- struct op_stream_read<T, decltype(std::declval<T>().deserialize(std::declval<std::istream&>()), void())>
- {
- inline size_t operator()(std::istream& is, T& t)
- {
- auto pos = is.tellg();
- t.deserialize(is);
- return convert_cast<size_t>(is.tellg() - pos);
- }
- };
-
- /* op_stream_write */
-
- template<class T, class Enable>
- struct op_stream_write
- {
- inline size_t operator()(std::ostream& os, const T& t) const
- {
- if (!os)
- throw exception("unable to write data to stream: invalid stream");
- os.write(reinterpret_cast<const char*>(&t), sizeof(t));
- if (!os)
- throw exception("unable to write data to stream: stream error");
- return sizeof(t);
- }
- };
-
- template<>
- struct op_stream_write<std::string, void>
- {
- inline size_t operator()(std::ostream& os, const std::string& t)
- {
- if (t.size() > std::numeric_limits<uint32_t>::max())
- throw exception("unable to write data to stream: string is to large");
- op_stream_write<uint32_t, void>()(os, convert_cast<uint32_t>(t.size()));
- if (!os)
- throw exception("unable to write data to stream: invalid stream");
- os.write(t.data(), convert_cast<std::streamsize>(t.size()));
- if (!os)
- throw exception("unable to write data to stream: stream error");
- return sizeof(uint32_t) + t.size();
- }
- };
-
- template<class T>
- struct op_stream_write<T, decltype(std::declval<T>().serialize(std::declval<std::ostream&>()), void())>
- {
- inline size_t operator()(std::ostream& os, const T& t)
- {
- auto pos = os.tellp();
- t.serialize(os);
- return convert_cast<size_t>(os.tellp() - pos);
- }
- };
-
- }
-
- }
|