FormattedStream.h 6.6 KB

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