circular_raw_ostream.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===-- llvm/Support/circular_raw_ostream.h - Buffered streams --*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file contains raw_ostream implementations for streams to do circular
  15. // buffering of their output.
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H
  19. #define LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H
  20. #include "llvm/Support/raw_ostream.h"
  21. namespace llvm {
  22. /// circular_raw_ostream - A raw_ostream which *can* save its data
  23. /// to a circular buffer, or can pass it through directly to an
  24. /// underlying stream if specified with a buffer of zero.
  25. ///
  26. class circular_raw_ostream : public raw_ostream {
  27. public:
  28. /// TAKE_OWNERSHIP - Tell this stream that it owns the underlying
  29. /// stream and is responsible for cleanup, memory management
  30. /// issues, etc.
  31. ///
  32. static constexpr bool TAKE_OWNERSHIP = true;
  33. /// REFERENCE_ONLY - Tell this stream it should not manage the
  34. /// held stream.
  35. ///
  36. static constexpr bool REFERENCE_ONLY = false;
  37. private:
  38. /// TheStream - The real stream we output to. We set it to be
  39. /// unbuffered, since we're already doing our own buffering.
  40. ///
  41. raw_ostream *TheStream = nullptr;
  42. /// OwnsStream - Are we responsible for managing the underlying
  43. /// stream?
  44. ///
  45. bool OwnsStream;
  46. /// BufferSize - The size of the buffer in bytes.
  47. ///
  48. size_t BufferSize;
  49. /// BufferArray - The actual buffer storage.
  50. ///
  51. char *BufferArray = nullptr;
  52. /// Cur - Pointer to the current output point in BufferArray.
  53. ///
  54. char *Cur;
  55. /// Filled - Indicate whether the buffer has been completely
  56. /// filled. This helps avoid garbage output.
  57. ///
  58. bool Filled = false;
  59. /// Banner - A pointer to a banner to print before dumping the
  60. /// log.
  61. ///
  62. const char *Banner;
  63. /// flushBuffer - Dump the contents of the buffer to Stream.
  64. ///
  65. void flushBuffer() {
  66. if (Filled)
  67. // Write the older portion of the buffer.
  68. TheStream->write(Cur, BufferArray + BufferSize - Cur);
  69. // Write the newer portion of the buffer.
  70. TheStream->write(BufferArray, Cur - BufferArray);
  71. Cur = BufferArray;
  72. Filled = false;
  73. }
  74. void write_impl(const char *Ptr, size_t Size) override;
  75. /// current_pos - Return the current position within the stream,
  76. /// not counting the bytes currently in the buffer.
  77. ///
  78. uint64_t current_pos() const override {
  79. // This has the same effect as calling TheStream.current_pos(),
  80. // but that interface is private.
  81. return TheStream->tell() - TheStream->GetNumBytesInBuffer();
  82. }
  83. public:
  84. /// circular_raw_ostream - Construct an optionally
  85. /// circular-buffered stream, handing it an underlying stream to
  86. /// do the "real" output.
  87. ///
  88. /// As a side effect, if BuffSize is nonzero, the given Stream is
  89. /// set to be Unbuffered. This is because circular_raw_ostream
  90. /// does its own buffering, so it doesn't want another layer of
  91. /// buffering to be happening underneath it.
  92. ///
  93. /// "Owns" tells the circular_raw_ostream whether it is
  94. /// responsible for managing the held stream, doing memory
  95. /// management of it, etc.
  96. ///
  97. circular_raw_ostream(raw_ostream &Stream, const char *Header,
  98. size_t BuffSize = 0, bool Owns = REFERENCE_ONLY)
  99. : raw_ostream(/*unbuffered*/ true), OwnsStream(Owns),
  100. BufferSize(BuffSize), Banner(Header) {
  101. if (BufferSize != 0)
  102. BufferArray = new char[BufferSize];
  103. Cur = BufferArray;
  104. setStream(Stream, Owns);
  105. }
  106. ~circular_raw_ostream() override {
  107. flush();
  108. flushBufferWithBanner();
  109. releaseStream();
  110. delete[] BufferArray;
  111. }
  112. bool is_displayed() const override {
  113. return TheStream->is_displayed();
  114. }
  115. /// setStream - Tell the circular_raw_ostream to output a
  116. /// different stream. "Owns" tells circular_raw_ostream whether
  117. /// it should take responsibility for managing the underlying
  118. /// stream.
  119. ///
  120. void setStream(raw_ostream &Stream, bool Owns = REFERENCE_ONLY) {
  121. releaseStream();
  122. TheStream = &Stream;
  123. OwnsStream = Owns;
  124. }
  125. /// flushBufferWithBanner - Force output of the buffer along with
  126. /// a small header.
  127. ///
  128. void flushBufferWithBanner();
  129. private:
  130. /// releaseStream - Delete the held stream if needed. Otherwise,
  131. /// transfer the buffer settings from this circular_raw_ostream
  132. /// back to the underlying stream.
  133. ///
  134. void releaseStream() {
  135. if (!TheStream)
  136. return;
  137. if (OwnsStream)
  138. delete TheStream;
  139. }
  140. };
  141. } // end llvm namespace
  142. #endif
  143. #ifdef __GNUC__
  144. #pragma GCC diagnostic pop
  145. #endif