Add classof implementations to the raw_ostream classes.
[oota-llvm.git] / include / llvm / Support / FormattedStream.h
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(SK_FORMATTED), TheStream(nullptr), DeleteStream(false),
89         Position(0, 0) {
90     setStream(Stream, Delete);
91   }
92   explicit formatted_raw_ostream()
93       : raw_ostream(SK_FORMATTED), TheStream(nullptr), DeleteStream(false),
94         Position(0, 0) {
95     Scanned = nullptr;
96   }
97
98   static bool classof(const raw_ostream *OS) {
99     return OS->getKind() == SK_FORMATTED;
100   }
101
102   ~formatted_raw_ostream() {
103     flush();
104     releaseStream();
105   }
106
107   void setStream(raw_ostream &Stream, bool Delete = false) {
108     releaseStream();
109
110     TheStream = &Stream;
111     DeleteStream = Delete;
112
113     // This formatted_raw_ostream inherits from raw_ostream, so it'll do its
114     // own buffering, and it doesn't need or want TheStream to do another
115     // layer of buffering underneath. Resize the buffer to what TheStream
116     // had been using, and tell TheStream not to do its own buffering.
117     if (size_t BufferSize = TheStream->GetBufferSize())
118       SetBufferSize(BufferSize);
119     else
120       SetUnbuffered();
121     TheStream->SetUnbuffered();
122
123     Scanned = nullptr;
124   }
125
126   /// PadToColumn - Align the output to some column number.  If the current
127   /// column is already equal to or more than NewCol, PadToColumn inserts one
128   /// space.
129   ///
130   /// \param NewCol - The column to move to.
131   formatted_raw_ostream &PadToColumn(unsigned NewCol);
132
133   /// getColumn - Return the column number
134   unsigned getColumn() { return Position.first; }
135
136   /// getLine - Return the line number
137   unsigned getLine() { return Position.second; }
138
139   raw_ostream &resetColor() override {
140     TheStream->resetColor();
141     return *this;
142   }
143
144   raw_ostream &reverseColor() override {
145     TheStream->reverseColor();
146     return *this;
147   }
148
149   raw_ostream &changeColor(enum Colors Color, bool Bold, bool BG) override {
150     TheStream->changeColor(Color, Bold, BG);
151     return *this;
152   }
153
154   bool is_displayed() const override {
155     return TheStream->is_displayed();
156   }
157
158 private:
159   void releaseStream() {
160     // Delete the stream if needed. Otherwise, transfer the buffer
161     // settings from this raw_ostream back to the underlying stream.
162     if (!TheStream)
163       return;
164     if (DeleteStream)
165       delete TheStream;
166     else if (size_t BufferSize = GetBufferSize())
167       TheStream->SetBufferSize(BufferSize);
168     else
169       TheStream->SetUnbuffered();
170   }
171 };
172
173 /// fouts() - This returns a reference to a formatted_raw_ostream for
174 /// standard output.  Use it like: fouts() << "foo" << "bar";
175 formatted_raw_ostream &fouts();
176
177 /// ferrs() - This returns a reference to a formatted_raw_ostream for
178 /// standard error.  Use it like: ferrs() << "foo" << "bar";
179 formatted_raw_ostream &ferrs();
180
181 /// fdbgs() - This returns a reference to a formatted_raw_ostream for
182 /// debug output.  Use it like: fdbgs() << "foo" << "bar";
183 formatted_raw_ostream &fdbgs();
184
185 } // end llvm namespace
186
187
188 #endif