No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

121 líneas
3.9 KiB

  1. #pragma once
  2. #include <iostream>
  3. #include "exception.h"
  4. namespace utl
  5. {
  6. namespace __impl
  7. {
  8. template<class T, class Enable = void>
  9. struct op_write_stream
  10. {
  11. inline void operator()(std::ostream& os, const T& t)
  12. {
  13. if (!os)
  14. throw exception("unable to write data to stream: invalid stream");
  15. os.write(reinterpret_cast<const char*>(&t), sizeof(t));
  16. if (!os)
  17. throw exception("unable to write data to stream: stream error");
  18. }
  19. };
  20. template<class T, class Enable = void>
  21. struct op_read_stream
  22. {
  23. inline void operator()(std::istream& is, T& t)
  24. {
  25. if (!is)
  26. throw exception("unable to read data from stream: invalid stream");
  27. if (is.read(reinterpret_cast<char*>(&t), sizeof(t)).gcount() != sizeof(t))
  28. throw exception("unable to read data from stream: EOF");
  29. if (!is)
  30. throw exception("unable to read data from stream: stream error");
  31. }
  32. };
  33. template<>
  34. struct op_write_stream<std::string, void>
  35. {
  36. inline void operator()(std::ostream& os, const std::string& t)
  37. {
  38. if (t.size() > std::numeric_limits<uint32_t>::max())
  39. throw exception("unable to write data to stream: string is to large");
  40. op_write_stream<uint32_t, void>()(os, static_cast<uint32_t>(t.size()));
  41. if (!os)
  42. throw exception("unable to write data to stream: invalid stream");
  43. os.write(t.data(), static_cast<std::streamsize>(t.size()));
  44. if (!os)
  45. throw exception("unable to write data to stream: stream error");
  46. }
  47. };
  48. template<>
  49. struct op_read_stream<std::string, void>
  50. {
  51. inline void operator()(std::istream& is, std::string& t)
  52. {
  53. uint32_t sz;
  54. op_read_stream<uint32_t, void>()(is, sz);
  55. if (!is)
  56. throw exception("unable to read data from stream: invalid stream");
  57. std::string tmp;
  58. tmp.resize(sz);
  59. if (is.read(const_cast<char*>(tmp.data()), sz).gcount() != sz)
  60. throw exception("unable to read data from stream: EOF");
  61. if (!is)
  62. throw exception("unable to read data from stream: stream error");
  63. t = std::move(tmp);
  64. }
  65. };
  66. template<class T>
  67. struct op_write_stream<T, decltype(std::declval<T>().serialize(std::declval<std::ostream&>()), void())>
  68. {
  69. inline void operator()(std::ostream& os, const T& t)
  70. { t.serialize(os); }
  71. };
  72. template<class T>
  73. struct op_read_stream<T, decltype(std::declval<T>().deserialize(std::declval<std::istream&>()), void())>
  74. {
  75. inline void operator()(std::istream& os, T& t)
  76. { t.deserialize(os); }
  77. };
  78. }
  79. struct stream_helper
  80. {
  81. template<class T>
  82. static inline void write(std::ostream& os, const T& t)
  83. { __impl::op_write_stream<T>()(os, t); }
  84. template<class T>
  85. static inline void read(std::istream& is, T& t)
  86. { __impl::op_read_stream<T>()(is, t); }
  87. template<class T>
  88. static inline T read(std::istream& is)
  89. {
  90. T t;
  91. read<T>(is, t);
  92. return std::move(t);
  93. }
  94. };
  95. struct stream_format_saver
  96. {
  97. std::ios state;
  98. std::ostream& stream;
  99. stream_format_saver(std::ostream& s) :
  100. state (nullptr),
  101. stream (s)
  102. { state.copyfmt(stream); }
  103. ~stream_format_saver()
  104. { stream.copyfmt(state); }
  105. };
  106. }