FormattedStream.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. //===-- llvm/Support/FormattedStream.h - Formatted streams ------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file contains raw_ostream implementations for streams to do
  10. // things like pretty-print comments.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_SUPPORT_FORMATTEDSTREAM_H
  14. #define LLVM_SUPPORT_FORMATTEDSTREAM_H
  15. #include "llvm/ADT/SmallString.h"
  16. #include "llvm/Support/raw_ostream.h"
  17. #include <utility>
  18. namespace llvm {
  19. /// formatted_raw_ostream - A raw_ostream that wraps another one and keeps track
  20. /// of line and column position, allowing padding out to specific column
  21. /// boundaries and querying the number of lines written to the stream. This
  22. /// assumes that the contents of the stream is valid UTF-8 encoded text. This
  23. /// doesn't attempt to handle everything Unicode can do (combining characters,
  24. /// right-to-left markers, etc), but should cover the cases likely to appear in
  25. /// source code or diagnostic messages.
  26. class formatted_raw_ostream : public raw_ostream {
  27. /// TheStream - The real stream we output to. We set it to be
  28. /// unbuffered, since we're already doing our own buffering.
  29. ///
  30. raw_ostream *TheStream;
  31. /// Position - The current output column and line of the data that's
  32. /// been flushed and the portion of the buffer that's been
  33. /// scanned. The line and column scheme is zero-based.
  34. ///
  35. std::pair<unsigned, unsigned> Position;
  36. /// Scanned - This points to one past the last character in the
  37. /// buffer we've scanned.
  38. ///
  39. const char *Scanned;
  40. /// PartialUTF8Char - Either empty or a prefix of a UTF-8 code unit sequence
  41. /// for a Unicode scalar value which should be prepended to the buffer for the
  42. /// next call to ComputePosition. This is needed when the buffer is flushed
  43. /// when it ends part-way through the UTF-8 encoding of a Unicode scalar
  44. /// value, so that we can compute the display width of the character once we
  45. /// have the rest of it.
  46. SmallString<4> PartialUTF8Char;
  47. void write_impl(const char *Ptr, size_t Size) override;
  48. /// current_pos - Return the current position within the stream,
  49. /// not counting the bytes currently in the buffer.
  50. uint64_t current_pos() const override {
  51. // Our current position in the stream is all the contents which have been
  52. // written to the underlying stream (*not* the current position of the
  53. // underlying stream).
  54. return TheStream->tell();
  55. }
  56. /// ComputePosition - Examine the given output buffer and figure out the new
  57. /// position after output. This is safe to call multiple times on the same
  58. /// buffer, as it records the most recently scanned character and resumes from
  59. /// there when the buffer has not been flushed.
  60. void ComputePosition(const char *Ptr, size_t size);
  61. /// UpdatePosition - scan the characters in [Ptr, Ptr+Size), and update the
  62. /// line and column numbers. Unlike ComputePosition, this must be called
  63. /// exactly once on each region of the buffer.
  64. void UpdatePosition(const char *Ptr, size_t Size);
  65. void setStream(raw_ostream &Stream) {
  66. releaseStream();
  67. TheStream = &Stream;
  68. // This formatted_raw_ostream inherits from raw_ostream, so it'll do its
  69. // own buffering, and it doesn't need or want TheStream to do another
  70. // layer of buffering underneath. Resize the buffer to what TheStream
  71. // had been using, and tell TheStream not to do its own buffering.
  72. if (size_t BufferSize = TheStream->GetBufferSize())
  73. SetBufferSize(BufferSize);
  74. else
  75. SetUnbuffered();
  76. TheStream->SetUnbuffered();
  77. Scanned = nullptr;
  78. }
  79. public:
  80. /// formatted_raw_ostream - Open the specified file for
  81. /// writing. If an error occurs, information about the error is
  82. /// put into ErrorInfo, and the stream should be immediately
  83. /// destroyed; the string will be empty if no error occurred.
  84. ///
  85. /// As a side effect, the given Stream is set to be Unbuffered.
  86. /// This is because formatted_raw_ostream does its own buffering,
  87. /// so it doesn't want another layer of buffering to be happening
  88. /// underneath it.
  89. ///
  90. formatted_raw_ostream(raw_ostream &Stream)
  91. : TheStream(nullptr), Position(0, 0) {
  92. setStream(Stream);
  93. }
  94. explicit formatted_raw_ostream() : TheStream(nullptr), Position(0, 0) {
  95. Scanned = nullptr;
  96. }
  97. ~formatted_raw_ostream() override {
  98. flush();
  99. releaseStream();
  100. }
  101. /// PadToColumn - Align the output to some column number. If the current
  102. /// column is already equal to or more than NewCol, PadToColumn inserts one
  103. /// space.
  104. ///
  105. /// \param NewCol - The column to move to.
  106. formatted_raw_ostream &PadToColumn(unsigned NewCol);
  107. unsigned getColumn() {
  108. // Calculate current position, taking buffer contents into account.
  109. ComputePosition(getBufferStart(), GetNumBytesInBuffer());
  110. return Position.first;
  111. }
  112. unsigned getLine() {
  113. // Calculate current position, taking buffer contents into account.
  114. ComputePosition(getBufferStart(), GetNumBytesInBuffer());
  115. return Position.second;
  116. }
  117. raw_ostream &resetColor() override {
  118. TheStream->resetColor();
  119. return *this;
  120. }
  121. raw_ostream &reverseColor() override {
  122. TheStream->reverseColor();
  123. return *this;
  124. }
  125. raw_ostream &changeColor(enum Colors Color, bool Bold, bool BG) override {
  126. TheStream->changeColor(Color, Bold, BG);
  127. return *this;
  128. }
  129. bool is_displayed() const override {
  130. return TheStream->is_displayed();
  131. }
  132. private:
  133. void releaseStream() {
  134. // Transfer the buffer settings from this raw_ostream back to the underlying
  135. // stream.
  136. if (!TheStream)
  137. return;
  138. if (size_t BufferSize = GetBufferSize())
  139. TheStream->SetBufferSize(BufferSize);
  140. else
  141. TheStream->SetUnbuffered();
  142. }
  143. };
  144. /// fouts() - This returns a reference to a formatted_raw_ostream for
  145. /// standard output. Use it like: fouts() << "foo" << "bar";
  146. formatted_raw_ostream &fouts();
  147. /// ferrs() - This returns a reference to a formatted_raw_ostream for
  148. /// standard error. Use it like: ferrs() << "foo" << "bar";
  149. formatted_raw_ostream &ferrs();
  150. /// fdbgs() - This returns a reference to a formatted_raw_ostream for
  151. /// debug output. Use it like: fdbgs() << "foo" << "bar";
  152. formatted_raw_ostream &fdbgs();
  153. } // end llvm namespace
  154. #endif