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   /// TheStream - The real stream we output to. We set it to be
     29   /// unbuffered, since we're already doing our own buffering.
     30   ///
     31   raw_ostream *TheStream;
     32 
     33   /// Position - The current output column and line of the data that's
     34   /// been flushed and the portion of the buffer that's been
     35   /// scanned.  The line and column scheme is zero-based.
     36   ///
     37   std::pair<unsigned, unsigned> Position;
     38 
     39   /// Scanned - This points to one past the last character in the
     40   /// buffer we've scanned.
     41   ///
     42   const char *Scanned;
     43 
     44   void write_impl(const char *Ptr, size_t Size) override;
     45 
     46   /// current_pos - Return the current position within the stream,
     47   /// not counting the bytes currently in the buffer.
     48   uint64_t current_pos() const override {
     49     // Our current position in the stream is all the contents which have been
     50     // written to the underlying stream (*not* the current position of the
     51     // underlying stream).
     52     return TheStream->tell();
     53   }
     54 
     55   /// ComputePosition - Examine the given output buffer and figure out the new
     56   /// position after output.
     57   ///
     58   void ComputePosition(const char *Ptr, size_t size);
     59 
     60   void setStream(raw_ostream &Stream) {
     61     releaseStream();
     62 
     63     TheStream = &Stream;
     64 
     65     // This formatted_raw_ostream inherits from raw_ostream, so it'll do its
     66     // own buffering, and it doesn't need or want TheStream to do another
     67     // layer of buffering underneath. Resize the buffer to what TheStream
     68     // had been using, and tell TheStream not to do its own buffering.
     69     if (size_t BufferSize = TheStream->GetBufferSize())
     70       SetBufferSize(BufferSize);
     71     else
     72       SetUnbuffered();
     73     TheStream->SetUnbuffered();
     74 
     75     Scanned = nullptr;
     76   }
     77 
     78 public:
     79   /// formatted_raw_ostream - Open the specified file for
     80   /// writing. If an error occurs, information about the error is
     81   /// put into ErrorInfo, and the stream should be immediately
     82   /// destroyed; the string will be empty if no error occurred.
     83   ///
     84   /// As a side effect, the given Stream is set to be Unbuffered.
     85   /// This is because formatted_raw_ostream does its own buffering,
     86   /// so it doesn't want another layer of buffering to be happening
     87   /// underneath it.
     88   ///
     89   formatted_raw_ostream(raw_ostream &Stream)
     90       : TheStream(nullptr), Position(0, 0) {
     91     setStream(Stream);
     92   }
     93   explicit formatted_raw_ostream() : TheStream(nullptr), Position(0, 0) {
     94     Scanned = nullptr;
     95   }
     96 
     97   ~formatted_raw_ostream() override {
     98     flush();
     99     releaseStream();
    100   }
    101 
    102   /// PadToColumn - Align the output to some column number.  If the current
    103   /// column is already equal to or more than NewCol, PadToColumn inserts one
    104   /// space.
    105   ///
    106   /// \param NewCol - The column to move to.
    107   formatted_raw_ostream &PadToColumn(unsigned NewCol);
    108 
    109   /// getColumn - Return the column number
    110   unsigned getColumn() { return Position.first; }
    111 
    112   /// getLine - Return the line number
    113   unsigned getLine() { return Position.second; }
    114 
    115   raw_ostream &resetColor() override {
    116     TheStream->resetColor();
    117     return *this;
    118   }
    119 
    120   raw_ostream &reverseColor() override {
    121     TheStream->reverseColor();
    122     return *this;
    123   }
    124 
    125   raw_ostream &changeColor(enum Colors Color, bool Bold, bool BG) override {
    126     TheStream->changeColor(Color, Bold, BG);
    127     return *this;
    128   }
    129 
    130   bool is_displayed() const override {
    131     return TheStream->is_displayed();
    132   }
    133 
    134 private:
    135   void releaseStream() {
    136     // Transfer the buffer settings from this raw_ostream back to the underlying
    137     // stream.
    138     if (!TheStream)
    139       return;
    140     if (size_t BufferSize = GetBufferSize())
    141       TheStream->SetBufferSize(BufferSize);
    142     else
    143       TheStream->SetUnbuffered();
    144   }
    145 };
    146 
    147 /// fouts() - This returns a reference to a formatted_raw_ostream for
    148 /// standard output.  Use it like: fouts() << "foo" << "bar";
    149 formatted_raw_ostream &fouts();
    150 
    151 /// ferrs() - This returns a reference to a formatted_raw_ostream for
    152 /// standard error.  Use it like: ferrs() << "foo" << "bar";
    153 formatted_raw_ostream &ferrs();
    154 
    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 
    159 } // end llvm namespace
    160 
    161 
    162 #endif
    163