• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
current_pos()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)
raw_ostream()88     : raw_ostream(), TheStream(nullptr), DeleteStream(false), Position(0, 0) {
89     setStream(Stream, Delete);
90   }
formatted_raw_ostream()91   explicit formatted_raw_ostream()
92     : raw_ostream(), TheStream(nullptr), DeleteStream(false), Position(0, 0) {
93     Scanned = nullptr;
94   }
95 
~formatted_raw_ostream()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
getColumn()128   unsigned getColumn() { return Position.first; }
129 
130   /// getLine - Return the line number
getLine()131   unsigned getLine() { return Position.second; }
132 
resetColor()133   raw_ostream &resetColor() override {
134     TheStream->resetColor();
135     return *this;
136   }
137 
reverseColor()138   raw_ostream &reverseColor() override {
139     TheStream->reverseColor();
140     return *this;
141   }
142 
changeColor(enum Colors Color,bool Bold,bool BG)143   raw_ostream &changeColor(enum Colors Color, bool Bold, bool BG) override {
144     TheStream->changeColor(Color, Bold, BG);
145     return *this;
146   }
147 
is_displayed()148   bool is_displayed() const override {
149     return TheStream->is_displayed();
150   }
151 
152 private:
releaseStream()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