Back to home page

EIC code displayed by LXR

 
 

    


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