25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 

179 satır
5.4 KiB

  1. #pragma once
  2. #include <cppcore/conversion/convert_cast.h>
  3. #include "stream.h"
  4. namespace cppcore
  5. {
  6. /* stream_helper_t */
  7. template<typename T_traits>
  8. template<class T>
  9. size_t stream_helper_t<T_traits>
  10. ::write(std::ostream& os, const T& t)
  11. { return __impl::op_stream_write<T>()(os, t); }
  12. template<typename T_traits>
  13. template<class T>
  14. size_t stream_helper_t<T_traits>
  15. ::read(std::istream& is, T& t)
  16. { return __impl::op_stream_read<T>()(is, t); }
  17. template<typename T_traits>
  18. template<class T>
  19. T stream_helper_t<T_traits>
  20. ::read(std::istream& is)
  21. {
  22. T t;
  23. read<T>(is, t);
  24. return std::move(t);
  25. }
  26. /* stream_writer_t */
  27. template<typename T_traits>
  28. stream_writer_t<T_traits>
  29. ::stream_writer_t(std::ostream& p_stream)
  30. : stream(p_stream)
  31. { }
  32. template<typename T_traits>
  33. template<class T>
  34. void stream_writer_t<T_traits>
  35. ::write(const T& t)
  36. { stream_helper_type::template write<T>(stream, t); }
  37. /* stream_reader_t */
  38. template<typename T_traits>
  39. stream_reader_t<T_traits>
  40. ::stream_reader_t(std::istream& p_stream)
  41. : stream(p_stream)
  42. { }
  43. template<typename T_traits>
  44. template<class T>
  45. size_t stream_reader_t<T_traits>
  46. ::read(T& t)
  47. { return stream_helper_type::template read<T>(stream, t); }
  48. template<typename T_traits>
  49. template<class T>
  50. T stream_reader_t<T_traits>
  51. ::read(std::istream& is)
  52. { return stream_helper_type::template read<T>(stream); }
  53. /* stream_format_saver */
  54. inline stream_format_saver
  55. ::stream_format_saver(std::ostream& s)
  56. : stream(s)
  57. { copyfmt(stream); }
  58. inline stream_format_saver
  59. ::~stream_format_saver()
  60. { stream.copyfmt(*this); }
  61. namespace __impl
  62. {
  63. /* op_stream_read */
  64. template<class T, class Enable>
  65. struct op_stream_read
  66. {
  67. inline size_t operator()(std::istream& is, T& t)
  68. {
  69. if (!is)
  70. throw exception("unable to read data from stream: invalid stream");
  71. if (is.read(reinterpret_cast<char*>(&t), sizeof(t)).gcount() != sizeof(t))
  72. throw exception("unable to read data from stream: EOF");
  73. if (!is)
  74. throw exception("unable to read data from stream: stream error");
  75. return sizeof(t);
  76. }
  77. };
  78. template<>
  79. struct op_stream_read<std::string, void>
  80. {
  81. inline size_t operator()(std::istream& is, std::string& t)
  82. {
  83. uint32_t sz;
  84. op_stream_read<uint32_t, void>()(is, sz);
  85. if (!is)
  86. throw exception("unable to read data from stream: invalid stream");
  87. std::string tmp;
  88. tmp.resize(sz);
  89. if (is.read(const_cast<char*>(tmp.data()), sz).gcount() != sz)
  90. throw exception("unable to read data from stream: EOF");
  91. if (!is)
  92. throw exception("unable to read data from stream: stream error");
  93. t = std::move(tmp);
  94. return sizeof(sz) + sz;
  95. }
  96. };
  97. template<class T>
  98. struct op_stream_read<T, decltype(std::declval<T>().deserialize(std::declval<std::istream&>()), void())>
  99. {
  100. inline size_t operator()(std::istream& is, T& t)
  101. {
  102. auto pos = is.tellg();
  103. t.deserialize(is);
  104. return convert_cast<size_t>(is.tellg() - pos);
  105. }
  106. };
  107. /* op_stream_write */
  108. template<class T, class Enable>
  109. struct op_stream_write
  110. {
  111. inline size_t operator()(std::ostream& os, const T& t) const
  112. {
  113. if (!os)
  114. throw exception("unable to write data to stream: invalid stream");
  115. os.write(reinterpret_cast<const char*>(&t), sizeof(t));
  116. if (!os)
  117. throw exception("unable to write data to stream: stream error");
  118. return sizeof(t);
  119. }
  120. };
  121. template<>
  122. struct op_stream_write<std::string, void>
  123. {
  124. inline size_t operator()(std::ostream& os, const std::string& t)
  125. {
  126. if (t.size() > std::numeric_limits<uint32_t>::max())
  127. throw exception("unable to write data to stream: string is to large");
  128. op_stream_write<uint32_t, void>()(os, convert_cast<uint32_t>(t.size()));
  129. if (!os)
  130. throw exception("unable to write data to stream: invalid stream");
  131. os.write(t.data(), convert_cast<std::streamsize>(t.size()));
  132. if (!os)
  133. throw exception("unable to write data to stream: stream error");
  134. return sizeof(uint32_t) + t.size();
  135. }
  136. };
  137. template<class T>
  138. struct op_stream_write<T, decltype(std::declval<T>().serialize(std::declval<std::ostream&>()), void())>
  139. {
  140. inline size_t operator()(std::ostream& os, const T& t)
  141. {
  142. auto pos = os.tellp();
  143. t.serialize(os);
  144. return convert_cast<size_t>(os.tellp() - pos);
  145. }
  146. };
  147. }
  148. }