circular_raw_ostream.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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;
  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;
  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;
  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), TheStream(nullptr),
  100. OwnsStream(Owns), BufferSize(BuffSize), BufferArray(nullptr),
  101. Filled(false), Banner(Header) {
  102. if (BufferSize != 0)
  103. BufferArray = new char[BufferSize];
  104. Cur = BufferArray;
  105. setStream(Stream, Owns);
  106. }
  107. ~circular_raw_ostream() override {
  108. flush();
  109. flushBufferWithBanner();
  110. releaseStream();
  111. delete[] BufferArray;
  112. }
  113. bool is_displayed() const override {
  114. return TheStream->is_displayed();
  115. }
  116. /// setStream - Tell the circular_raw_ostream to output a
  117. /// different stream. "Owns" tells circular_raw_ostream whether
  118. /// it should take responsibility for managing the underlying
  119. /// stream.
  120. ///
  121. void setStream(raw_ostream &Stream, bool Owns = REFERENCE_ONLY) {
  122. releaseStream();
  123. TheStream = &Stream;
  124. OwnsStream = Owns;
  125. }
  126. /// flushBufferWithBanner - Force output of the buffer along with
  127. /// a small header.
  128. ///
  129. void flushBufferWithBanner();
  130. private:
  131. /// releaseStream - Delete the held stream if needed. Otherwise,
  132. /// transfer the buffer settings from this circular_raw_ostream
  133. /// back to the underlying stream.
  134. ///
  135. void releaseStream() {
  136. if (!TheStream)
  137. return;
  138. if (OwnsStream)
  139. delete TheStream;
  140. }
  141. };
  142. } // end llvm namespace
  143. #endif
  144. #ifdef __GNUC__
  145. #pragma GCC diagnostic pop
  146. #endif