|
|
|||
File indexing completed on 2026-05-10 08:44:30
0001 //===-- llvm/Support/FormattedStream.h - Formatted streams ------*- C++ -*-===// 0002 // 0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 0004 // See https://llvm.org/LICENSE.txt for license information. 0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 0006 // 0007 //===----------------------------------------------------------------------===// 0008 // 0009 // This file contains raw_ostream implementations for streams to do 0010 // things like pretty-print comments. 0011 // 0012 //===----------------------------------------------------------------------===// 0013 0014 #ifndef LLVM_SUPPORT_FORMATTEDSTREAM_H 0015 #define LLVM_SUPPORT_FORMATTEDSTREAM_H 0016 0017 #include "llvm/ADT/SmallString.h" 0018 #include "llvm/Support/raw_ostream.h" 0019 #include <utility> 0020 0021 namespace llvm { 0022 0023 /// formatted_raw_ostream - A raw_ostream that wraps another one and keeps track 0024 /// of line and column position, allowing padding out to specific column 0025 /// boundaries and querying the number of lines written to the stream. This 0026 /// assumes that the contents of the stream is valid UTF-8 encoded text. This 0027 /// doesn't attempt to handle everything Unicode can do (combining characters, 0028 /// right-to-left markers, etc), but should cover the cases likely to appear in 0029 /// source code or diagnostic messages. 0030 class formatted_raw_ostream : public raw_ostream { 0031 /// TheStream - The real stream we output to. We set it to be 0032 /// unbuffered, since we're already doing our own buffering. 0033 /// 0034 raw_ostream *TheStream; 0035 0036 /// Position - The current output column and line of the data that's 0037 /// been flushed and the portion of the buffer that's been 0038 /// scanned. The line and column scheme is zero-based. 0039 /// 0040 std::pair<unsigned, unsigned> Position; 0041 0042 /// Scanned - This points to one past the last character in the 0043 /// buffer we've scanned. 0044 /// 0045 const char *Scanned; 0046 0047 /// PartialUTF8Char - Either empty or a prefix of a UTF-8 code unit sequence 0048 /// for a Unicode scalar value which should be prepended to the buffer for the 0049 /// next call to ComputePosition. This is needed when the buffer is flushed 0050 /// when it ends part-way through the UTF-8 encoding of a Unicode scalar 0051 /// value, so that we can compute the display width of the character once we 0052 /// have the rest of it. 0053 SmallString<4> PartialUTF8Char; 0054 0055 /// DisableScan - Temporarily disable scanning of output. Used to ignore color 0056 /// codes. 0057 bool DisableScan; 0058 0059 void write_impl(const char *Ptr, size_t Size) override; 0060 0061 /// current_pos - Return the current position within the stream, 0062 /// not counting the bytes currently in the buffer. 0063 uint64_t current_pos() const override { 0064 // Our current position in the stream is all the contents which have been 0065 // written to the underlying stream (*not* the current position of the 0066 // underlying stream). 0067 return TheStream->tell(); 0068 } 0069 0070 /// ComputePosition - Examine the given output buffer and figure out the new 0071 /// position after output. This is safe to call multiple times on the same 0072 /// buffer, as it records the most recently scanned character and resumes from 0073 /// there when the buffer has not been flushed. 0074 void ComputePosition(const char *Ptr, size_t size); 0075 0076 /// UpdatePosition - scan the characters in [Ptr, Ptr+Size), and update the 0077 /// line and column numbers. Unlike ComputePosition, this must be called 0078 /// exactly once on each region of the buffer. 0079 void UpdatePosition(const char *Ptr, size_t Size); 0080 0081 void setStream(raw_ostream &Stream) { 0082 releaseStream(); 0083 0084 TheStream = &Stream; 0085 0086 // This formatted_raw_ostream inherits from raw_ostream, so it'll do its 0087 // own buffering, and it doesn't need or want TheStream to do another 0088 // layer of buffering underneath. Resize the buffer to what TheStream 0089 // had been using, and tell TheStream not to do its own buffering. 0090 if (size_t BufferSize = TheStream->GetBufferSize()) 0091 SetBufferSize(BufferSize); 0092 else 0093 SetUnbuffered(); 0094 TheStream->SetUnbuffered(); 0095 0096 enable_colors(TheStream->colors_enabled()); 0097 0098 Scanned = nullptr; 0099 } 0100 0101 void PreDisableScan() { 0102 assert(!DisableScan); 0103 ComputePosition(getBufferStart(), GetNumBytesInBuffer()); 0104 assert(PartialUTF8Char.empty()); 0105 DisableScan = true; 0106 } 0107 0108 void PostDisableScan() { 0109 assert(DisableScan); 0110 DisableScan = false; 0111 Scanned = getBufferStart() + GetNumBytesInBuffer(); 0112 } 0113 0114 struct DisableScanScope { 0115 formatted_raw_ostream *S; 0116 0117 DisableScanScope(formatted_raw_ostream *FRO) : S(FRO) { 0118 S->PreDisableScan(); 0119 } 0120 ~DisableScanScope() { S->PostDisableScan(); } 0121 }; 0122 0123 public: 0124 /// formatted_raw_ostream - Open the specified file for 0125 /// writing. If an error occurs, information about the error is 0126 /// put into ErrorInfo, and the stream should be immediately 0127 /// destroyed; the string will be empty if no error occurred. 0128 /// 0129 /// As a side effect, the given Stream is set to be Unbuffered. 0130 /// This is because formatted_raw_ostream does its own buffering, 0131 /// so it doesn't want another layer of buffering to be happening 0132 /// underneath it. 0133 /// 0134 formatted_raw_ostream(raw_ostream &Stream) 0135 : TheStream(nullptr), Position(0, 0), DisableScan(false) { 0136 setStream(Stream); 0137 } 0138 explicit formatted_raw_ostream() 0139 : TheStream(nullptr), Position(0, 0), Scanned(nullptr), 0140 DisableScan(false) {} 0141 0142 ~formatted_raw_ostream() override { 0143 flush(); 0144 releaseStream(); 0145 } 0146 0147 /// PadToColumn - Align the output to some column number. If the current 0148 /// column is already equal to or more than NewCol, PadToColumn inserts one 0149 /// space. 0150 /// 0151 /// \param NewCol - The column to move to. 0152 formatted_raw_ostream &PadToColumn(unsigned NewCol); 0153 0154 unsigned getColumn() { 0155 // Calculate current position, taking buffer contents into account. 0156 ComputePosition(getBufferStart(), GetNumBytesInBuffer()); 0157 return Position.first; 0158 } 0159 0160 unsigned getLine() { 0161 // Calculate current position, taking buffer contents into account. 0162 ComputePosition(getBufferStart(), GetNumBytesInBuffer()); 0163 return Position.second; 0164 } 0165 0166 raw_ostream &resetColor() override { 0167 if (colors_enabled()) { 0168 DisableScanScope S(this); 0169 raw_ostream::resetColor(); 0170 } 0171 return *this; 0172 } 0173 0174 raw_ostream &reverseColor() override { 0175 if (colors_enabled()) { 0176 DisableScanScope S(this); 0177 raw_ostream::reverseColor(); 0178 } 0179 return *this; 0180 } 0181 0182 raw_ostream &changeColor(enum Colors Color, bool Bold, bool BG) override { 0183 if (colors_enabled()) { 0184 DisableScanScope S(this); 0185 raw_ostream::changeColor(Color, Bold, BG); 0186 } 0187 return *this; 0188 } 0189 0190 bool is_displayed() const override { 0191 return TheStream->is_displayed(); 0192 } 0193 0194 private: 0195 void releaseStream() { 0196 // Transfer the buffer settings from this raw_ostream back to the underlying 0197 // stream. 0198 if (!TheStream) 0199 return; 0200 if (size_t BufferSize = GetBufferSize()) 0201 TheStream->SetBufferSize(BufferSize); 0202 else 0203 TheStream->SetUnbuffered(); 0204 } 0205 }; 0206 0207 /// fouts() - This returns a reference to a formatted_raw_ostream for 0208 /// standard output. Use it like: fouts() << "foo" << "bar"; 0209 formatted_raw_ostream &fouts(); 0210 0211 /// ferrs() - This returns a reference to a formatted_raw_ostream for 0212 /// standard error. Use it like: ferrs() << "foo" << "bar"; 0213 formatted_raw_ostream &ferrs(); 0214 0215 /// fdbgs() - This returns a reference to a formatted_raw_ostream for 0216 /// debug output. Use it like: fdbgs() << "foo" << "bar"; 0217 formatted_raw_ostream &fdbgs(); 0218 0219 } // end llvm namespace 0220 0221 0222 #endif
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|