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