Home | History | Annotate | Download | only in Support
      1 //===-- llvm/Support/FormattedStream.h - Formatted streams ------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file contains raw_ostream implementations for streams to do
     11 // things like pretty-print comments.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef LLVM_SUPPORT_FORMATTEDSTREAM_H
     16 #define LLVM_SUPPORT_FORMATTEDSTREAM_H
     17 
     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.
     26 ///
     27 class formatted_raw_ostream : public raw_ostream {
     28 public:
     29   /// DELETE_STREAM - Tell the destructor to delete the held stream.
     30   ///
     31   static const bool DELETE_STREAM = true;
     32 
     33   /// PRESERVE_STREAM - Tell the destructor to not delete the held
     34   /// stream.
     35   ///
     36   static const bool PRESERVE_STREAM = false;
     37 
     38 private:
     39   /// TheStream - The real stream we output to. We set it to be
     40   /// unbuffered, since we're already doing our own buffering.
     41   ///
     42   raw_ostream *TheStream;
     43 
     44   /// DeleteStream - Do we need to delete TheStream in the
     45   /// destructor?
     46   ///
     47   bool DeleteStream;
     48 
     49   /// Position - The current output column and line of the data that's
     50   /// been flushed and the portion of the buffer that's been
     51   /// scanned.  The line and column scheme is zero-based.
     52   ///
     53   std::pair<unsigned, unsigned> Position;
     54 
     55   /// Scanned - This points to one past the last character in the
     56   /// buffer we've scanned.
     57   ///
     58   const char *Scanned;
     59 
     60   void write_impl(const char *Ptr, size_t Size) override;
     61 
     62   /// current_pos - Return the current position within the stream,
     63   /// not counting the bytes currently in the buffer.
     64   uint64_t current_pos() const override {
     65     // Our current position in the stream is all the contents which have been
     66     // written to the underlying stream (*not* the current position of the
     67     // underlying stream).
     68     return TheStream->tell();
     69   }
     70 
     71   /// ComputePosition - Examine the given output buffer and figure out the new
     72   /// position after output.
     73   ///
     74   void ComputePosition(const char *Ptr, size_t size);
     75 
     76 public:
     77   /// formatted_raw_ostream - Open the specified file for
     78   /// writing. If an error occurs, information about the error is
     79   /// put into ErrorInfo, and the stream should be immediately
     80   /// destroyed; the string will be empty if no error occurred.
     81   ///
     82   /// As a side effect, the given Stream is set to be Unbuffered.
     83   /// This is because formatted_raw_ostream does its own buffering,
     84   /// so it doesn't want another layer of buffering to be happening
     85   /// underneath it.
     86   ///
     87   formatted_raw_ostream(raw_ostream &Stream, bool Delete = false)
     88     : raw_ostream(), TheStream(nullptr), DeleteStream(false), Position(0, 0) {
     89     setStream(Stream, Delete);
     90   }
     91   explicit formatted_raw_ostream()
     92     : raw_ostream(), TheStream(nullptr), DeleteStream(false), Position(0, 0) {
     93     Scanned = nullptr;
     94   }
     95 
     96   ~formatted_raw_ostream() {
     97     flush();
     98     releaseStream();
     99   }
    100 
    101   void setStream(raw_ostream &Stream, bool Delete = false) {
    102     releaseStream();
    103 
    104     TheStream = &Stream;
    105     DeleteStream = Delete;
    106 
    107     // This formatted_raw_ostream inherits from raw_ostream, so it'll do its
    108     // own buffering, and it doesn't need or want TheStream to do another
    109     // layer of buffering underneath. Resize the buffer to what TheStream
    110     // had been using, and tell TheStream not to do its own buffering.
    111     if (size_t BufferSize = TheStream->GetBufferSize())
    112       SetBufferSize(BufferSize);
    113     else
    114       SetUnbuffered();
    115     TheStream->SetUnbuffered();
    116 
    117     Scanned = nullptr;
    118   }
    119 
    120   /// PadToColumn - Align the output to some column number.  If the current
    121   /// column is already equal to or more than NewCol, PadToColumn inserts one
    122   /// space.
    123   ///
    124   /// \param NewCol - The column to move to.
    125   formatted_raw_ostream &PadToColumn(unsigned NewCol);
    126 
    127   /// getColumn - Return the column number
    128   unsigned getColumn() { return Position.first; }
    129 
    130   /// getLine - Return the line number
    131   unsigned getLine() { return Position.second; }
    132 
    133   raw_ostream &resetColor() override {
    134     TheStream->resetColor();
    135     return *this;
    136   }
    137 
    138   raw_ostream &reverseColor() override {
    139     TheStream->reverseColor();
    140     return *this;
    141   }
    142 
    143   raw_ostream &changeColor(enum Colors Color, bool Bold, bool BG) override {
    144     TheStream->changeColor(Color, Bold, BG);
    145     return *this;
    146   }
    147 
    148   bool is_displayed() const override {
    149     return TheStream->is_displayed();
    150   }
    151 
    152 private:
    153   void releaseStream() {
    154     // Delete the stream if needed. Otherwise, transfer the buffer
    155     // settings from this raw_ostream back to the underlying stream.
    156     if (!TheStream)
    157       return;
    158     if (DeleteStream)
    159       delete TheStream;
    160     else if (size_t BufferSize = GetBufferSize())
    161       TheStream->SetBufferSize(BufferSize);
    162     else
    163       TheStream->SetUnbuffered();
    164   }
    165 };
    166 
    167 /// fouts() - This returns a reference to a formatted_raw_ostream for
    168 /// standard output.  Use it like: fouts() << "foo" << "bar";
    169 formatted_raw_ostream &fouts();
    170 
    171 /// ferrs() - This returns a reference to a formatted_raw_ostream for
    172 /// standard error.  Use it like: ferrs() << "foo" << "bar";
    173 formatted_raw_ostream &ferrs();
    174 
    175 /// fdbgs() - This returns a reference to a formatted_raw_ostream for
    176 /// debug output.  Use it like: fdbgs() << "foo" << "bar";
    177 formatted_raw_ostream &fdbgs();
    178 
    179 } // end llvm namespace
    180 
    181 
    182 #endif
    183