output.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. #pragma once
  2. #include "fwd.h"
  3. #include "labeled.h"
  4. #include <util/generic/noncopyable.h>
  5. #include <util/generic/string.h>
  6. #include <util/generic/strbuf.h>
  7. #include <util/generic/typetraits.h>
  8. #include <type_traits>
  9. /**
  10. * @addtogroup Streams_Base
  11. * @{
  12. */
  13. /**
  14. * Abstract output stream.
  15. */
  16. class IOutputStream: public TNonCopyable {
  17. public:
  18. /**
  19. * Data block for output.
  20. */
  21. struct TPart {
  22. inline TPart(const void* Buf, size_t Len) noexcept
  23. : buf(Buf)
  24. , len(Len)
  25. {
  26. }
  27. inline TPart(const TStringBuf s) noexcept
  28. : buf(s.data())
  29. , len(s.size())
  30. {
  31. }
  32. inline TPart() noexcept
  33. : buf(nullptr)
  34. , len(0)
  35. {
  36. }
  37. inline ~TPart() = default;
  38. static inline TPart CrLf() noexcept {
  39. return TPart("\r\n", 2);
  40. }
  41. const void* buf;
  42. size_t len;
  43. };
  44. IOutputStream() noexcept;
  45. virtual ~IOutputStream();
  46. IOutputStream(IOutputStream&&) noexcept {
  47. }
  48. IOutputStream& operator=(IOutputStream&&) noexcept {
  49. return *this;
  50. }
  51. /**
  52. * Writes into this stream.
  53. *
  54. * @param buf Data to write.
  55. * @param len Number of bytes to write.
  56. */
  57. inline void Write(const void* buf, size_t len) {
  58. if (len) {
  59. DoWrite(buf, len);
  60. }
  61. }
  62. /**
  63. * Writes a string into this stream.
  64. *
  65. * @param st String to write.
  66. */
  67. inline void Write(const TStringBuf st) {
  68. Write(st.data(), st.size());
  69. }
  70. /**
  71. * Writes several data blocks into this stream.
  72. *
  73. * @param parts Pointer to the start of the data blocks
  74. * array.
  75. * @param count Number of data blocks to write.
  76. */
  77. inline void Write(const TPart* parts, size_t count) {
  78. if (count > 1) {
  79. DoWriteV(parts, count);
  80. } else if (count) {
  81. DoWrite(parts->buf, parts->len);
  82. }
  83. }
  84. /**
  85. * Writes a single character into this stream.
  86. *
  87. * @param ch Character to write.
  88. */
  89. inline void Write(char ch) {
  90. DoWriteC(ch);
  91. }
  92. /**
  93. * Flushes this stream's buffer, if any.
  94. *
  95. * Note that this can also be done with a `Flush` manipulator:
  96. * @code
  97. * stream << "some string" << Flush;
  98. * @endcode
  99. */
  100. inline void Flush() {
  101. DoFlush();
  102. }
  103. /**
  104. * Flushes and closes this stream. No more data can be written into a stream
  105. * once it's closed.
  106. */
  107. inline void Finish() {
  108. DoFinish();
  109. }
  110. protected:
  111. /**
  112. * Writes into this stream.
  113. *
  114. * @param buf Data to write.
  115. * @param len Number of bytes to write.
  116. * @throws yexception If IO error occurs.
  117. */
  118. virtual void DoWrite(const void* buf, size_t len) = 0;
  119. /**
  120. * Writes several data blocks into this stream.
  121. *
  122. * @param parts Pointer to the start of the data blocks
  123. * array.
  124. * @param count Number of data blocks to write.
  125. * @throws yexception If IO error occurs.
  126. */
  127. virtual void DoWriteV(const TPart* parts, size_t count);
  128. /**
  129. * Writes a single character into this stream. Can be overridden with a faster implementation.
  130. *
  131. * @param ch Character to write.
  132. */
  133. virtual void DoWriteC(char ch);
  134. /**
  135. * Flushes this stream's buffer, if any.
  136. *
  137. * @throws yexception If IO error occurs.
  138. */
  139. virtual void DoFlush();
  140. /**
  141. * Flushes and closes this stream. No more data can be written into a stream
  142. * once it's closed.
  143. *
  144. * @throws yexception If IO error occurs.
  145. */
  146. virtual void DoFinish();
  147. };
  148. /**
  149. * `operator<<` for `IOutputStream` by default delegates to this function.
  150. *
  151. * Note that while `operator<<` uses overloading (and thus argument-dependent
  152. * lookup), `Out` uses template specializations. This makes it possible to
  153. * have a single `Out` declaration, and then just provide specializations in
  154. * cpp files, letting the linker figure everything else out. This approach
  155. * reduces compilation times.
  156. *
  157. * However, if the flexibility of overload resolution is needed, then one should
  158. * just overload `operator<<`.
  159. *
  160. * @param out Output stream to write into.
  161. * @param value Value to write.
  162. */
  163. template <class T>
  164. void Out(IOutputStream& out, typename TTypeTraits<T>::TFuncParam value);
  165. #define Y_DECLARE_OUT_SPEC(MODIF, T, stream, value) \
  166. template <> \
  167. MODIF void Out<T>(IOutputStream & stream, TTypeTraits<T>::TFuncParam value)
  168. template <>
  169. inline void Out<const char*>(IOutputStream& o, const char* t) {
  170. if (t) {
  171. o.Write(t);
  172. } else {
  173. o.Write("(null)");
  174. }
  175. }
  176. template <>
  177. void Out<const wchar16*>(IOutputStream& o, const wchar16* w);
  178. template <>
  179. void Out<const wchar32*>(IOutputStream& o, const wchar32* w);
  180. static inline IOutputStream& operator<<(IOutputStream& o, TStreamManipulator m) {
  181. m(o);
  182. return o;
  183. }
  184. static inline IOutputStream& operator<<(IOutputStream& o, const char* t) {
  185. Out<const char*>(o, t);
  186. return o;
  187. }
  188. static inline IOutputStream& operator<<(IOutputStream& o, char* t) {
  189. Out<const char*>(o, t);
  190. return o;
  191. }
  192. template <class T>
  193. static inline std::enable_if_t<std::is_scalar<T>::value, IOutputStream&> operator<<(IOutputStream& o, T t) {
  194. Out<T>(o, t);
  195. return o;
  196. }
  197. template <class T>
  198. static inline std::enable_if_t<!std::is_scalar<T>::value, IOutputStream&> operator<<(IOutputStream& o, const T& t) {
  199. Out<T>(o, t);
  200. return o;
  201. }
  202. static inline IOutputStream& operator<<(IOutputStream& o, const wchar16* t) {
  203. Out<const wchar16*>(o, t);
  204. return o;
  205. }
  206. static inline IOutputStream& operator<<(IOutputStream& o, wchar16* t) {
  207. Out<const wchar16*>(o, t);
  208. return o;
  209. }
  210. static inline IOutputStream& operator<<(IOutputStream& o, const wchar32* t) {
  211. Out<const wchar32*>(o, t);
  212. return o;
  213. }
  214. static inline IOutputStream& operator<<(IOutputStream& o, wchar32* t) {
  215. Out<const wchar32*>(o, t);
  216. return o;
  217. }
  218. namespace NPrivate {
  219. IOutputStream& StdOutStream() noexcept;
  220. IOutputStream& StdErrStream() noexcept;
  221. } // namespace NPrivate
  222. /**
  223. * Standard output stream.
  224. */
  225. #define Cout (::NPrivate::StdOutStream())
  226. /**
  227. * Standard error stream.
  228. */
  229. #define Cerr (::NPrivate::StdErrStream())
  230. /**
  231. * Standard log stream.
  232. */
  233. #define Clog Cerr
  234. /**
  235. * End-of-line output manipulator, basically the same as `std::endl`.
  236. */
  237. static inline void Endl(IOutputStream& o) {
  238. (o << '\n').Flush();
  239. }
  240. /**
  241. * Flushing stream manipulator, basically the same as `std::flush`.
  242. */
  243. static inline void Flush(IOutputStream& o) {
  244. o.Flush();
  245. }
  246. /*
  247. * Also see format.h for additional manipulators.
  248. */
  249. #include "debug.h"
  250. void RedirectStdioToAndroidLog(bool redirect);
  251. /** @} */