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