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   virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE;
     61 
     62   /// current_pos - Return the current position within the stream,
     63   /// not counting the bytes currently in the buffer.
     64   virtual uint64_t current_pos() const LLVM_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(0), DeleteStream(false), Position(0, 0) {
     89     setStream(Stream, Delete);
     90   }
     91   explicit formatted_raw_ostream()
     92     : raw_ostream(), TheStream(0), DeleteStream(false), Position(0, 0) {
     93     Scanned = 0;
     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 = 0;
    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 private:
    134   void releaseStream() {
    135     // Delete the stream if needed. Otherwise, transfer the buffer
    136     // settings from this raw_ostream back to the underlying stream.
    137     if (!TheStream)
    138       return;
    139     if (DeleteStream)
    140       delete TheStream;
    141     else if (size_t BufferSize = GetBufferSize())
    142       TheStream->SetBufferSize(BufferSize);
    143     else
    144       TheStream->SetUnbuffered();
    145   }
    146 };
    147 
    148 /// fouts() - This returns a reference to a formatted_raw_ostream for
    149 /// standard output.  Use it like: fouts() << "foo" << "bar";
    150 formatted_raw_ostream &fouts();
    151 
    152 /// ferrs() - This returns a reference to a formatted_raw_ostream for
    153 /// standard error.  Use it like: ferrs() << "foo" << "bar";
    154 formatted_raw_ostream &ferrs();
    155 
    156 /// fdbgs() - This returns a reference to a formatted_raw_ostream for
    157 /// debug output.  Use it like: fdbgs() << "foo" << "bar";
    158 formatted_raw_ostream &fdbgs();
    159 
    160 } // end llvm namespace
    161 
    162 
    163 #endif
    164