Add raw_stream adaptors that write into an std::string and SmallVector/SmallString.
[oota-llvm.git] / lib / Support / raw_ostream.cpp
1 //===--- raw_ostream.cpp - Implement the raw_ostream classes --------------===//
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 implements support for bulk buffered stream output.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Support/raw_ostream.h"
15 #include "llvm/Support/Format.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/Config/config.h"
18 #include <ostream>
19
20 #if defined(HAVE_UNISTD_H)
21 # include <unistd.h>
22 #endif
23 #if defined(HAVE_FCNTL_H)
24 # include <fcntl.h>
25 #endif
26
27 #if defined(_MSC_VER)
28 #include <io.h>
29 #ifndef STDIN_FILENO
30 # define STDIN_FILENO 0
31 #endif
32 #ifndef STDOUT_FILENO
33 # define STDOUT_FILENO 1
34 #endif
35 #ifndef STDERR_FILENO
36 # define STDERR_FILENO 2
37 #endif
38 #endif
39
40 using namespace llvm;
41
42
43 // An out of line virtual method to provide a home for the class vtable.
44 void raw_ostream::handle() {}
45
46 raw_ostream &raw_ostream::operator<<(unsigned long N) {
47   // Zero is a special case.
48   if (N == 0)
49     return *this << '0';
50   
51   char NumberBuffer[20];
52   char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
53   char *CurPtr = EndPtr;
54   
55   while (N) {
56     *--CurPtr = '0' + char(N % 10);
57     N /= 10;
58   }
59   return write(CurPtr, EndPtr-CurPtr);
60 }
61
62 raw_ostream &raw_ostream::operator<<(long N) {
63   if (N <  0) {
64     if (OutBufCur >= OutBufEnd)
65       flush_impl();
66     *OutBufCur++ = '-';
67     
68     N = -N;
69   }
70   
71   return this->operator<<(static_cast<unsigned long>(N));
72 }
73
74 raw_ostream &raw_ostream::operator<<(unsigned long long N) {
75   // Zero is a special case.
76   if (N == 0)
77     return *this << '0';
78   
79   char NumberBuffer[20];
80   char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
81   char *CurPtr = EndPtr;
82   
83   while (N) {
84     *--CurPtr = '0' + char(N % 10);
85     N /= 10;
86   }
87   return write(CurPtr, EndPtr-CurPtr);
88 }
89
90 raw_ostream &raw_ostream::operator<<(long long N) {
91   if (N <  0) {
92     if (OutBufCur >= OutBufEnd)
93       flush_impl();
94     *OutBufCur++ = '-';
95     
96     N = -N;
97   }
98   
99   return this->operator<<(static_cast<unsigned long long>(N));
100 }
101
102 raw_ostream &raw_ostream::operator<<(const void *P) {
103   // FIXME: This could be much faster if it matters.
104   return *this << format("%p", P);
105 }
106
107
108 raw_ostream &raw_ostream::write(const char *Ptr, unsigned Size) {
109   if (OutBufCur+Size > OutBufEnd)
110     flush_impl();
111   
112   // Handle short strings specially, memcpy isn't very good at very short
113   // strings.
114   switch (Size) {
115   case 4: OutBufCur[3] = Ptr[3]; // FALL THROUGH
116   case 3: OutBufCur[2] = Ptr[2]; // FALL THROUGH
117   case 2: OutBufCur[1] = Ptr[1]; // FALL THROUGH
118   case 1: OutBufCur[0] = Ptr[0]; // FALL THROUGH
119   case 0: break;
120   default:
121     // Normally the string to emit is shorter than the buffer.
122     if (Size <= unsigned(OutBufEnd-OutBufStart)) {
123       memcpy(OutBufCur, Ptr, Size);
124       break;
125     }
126
127     // If emitting a string larger than our buffer, emit in chunks.  In this
128     // case we know that we just flushed the buffer.
129     while (Size) {
130       unsigned NumToEmit = OutBufEnd-OutBufStart;
131       if (Size < NumToEmit) NumToEmit = Size;
132       assert(OutBufCur == OutBufStart);
133       memcpy(OutBufStart, Ptr, NumToEmit);
134       Ptr += NumToEmit;
135       Size -= NumToEmit;
136       OutBufCur = OutBufStart + NumToEmit;
137       flush_impl();
138     }
139     break;
140   }
141   OutBufCur += Size;
142   return *this;
143 }
144
145 // Formatted output.
146 raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) {
147   // If we have more than a few bytes left in our output buffer, try formatting
148   // directly onto its end.
149   unsigned NextBufferSize = 127;
150   if (OutBufEnd-OutBufCur > 3) {
151     unsigned BufferBytesLeft = OutBufEnd-OutBufCur;
152     unsigned BytesUsed = Fmt.print(OutBufCur, BufferBytesLeft);
153     
154     // Common case is that we have plenty of space.
155     if (BytesUsed < BufferBytesLeft) {
156       OutBufCur += BytesUsed;
157       return *this;
158     }
159     
160     // Otherwise, we overflowed and the return value tells us the size to try
161     // again with.
162     NextBufferSize = BytesUsed;
163   }
164   
165   // If we got here, we didn't have enough space in the output buffer for the
166   // string.  Try printing into a SmallVector that is resized to have enough
167   // space.  Iterate until we win.
168   SmallVector<char, 128> V;
169   
170   while (1) {
171     V.resize(NextBufferSize);
172     
173     // Try formatting into the SmallVector.
174     unsigned BytesUsed = Fmt.print(&V[0], NextBufferSize);
175     
176     // If BytesUsed fit into the vector, we win.
177     if (BytesUsed < NextBufferSize)
178       return write(&V[0], BytesUsed);
179     
180     // Otherwise, try again with a new size.
181     assert(BytesUsed > NextBufferSize && "Didn't grow buffer!?");
182     NextBufferSize = BytesUsed;
183   }
184 }
185
186 //===----------------------------------------------------------------------===//
187 //  Formatted Output
188 //===----------------------------------------------------------------------===//
189
190 // Out of line virtual method.
191 void format_object_base::home() {
192 }
193
194 //===----------------------------------------------------------------------===//
195 //  raw_fd_ostream
196 //===----------------------------------------------------------------------===//
197
198 /// raw_fd_ostream - Open the specified file for writing.  If an error occurs,
199 /// information about the error is put into ErrorInfo, and the stream should
200 /// be immediately destroyed.
201 raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo) {
202   // Handle "-" as stdout.
203   if (Filename[0] == '-' && Filename[1] == 0) {
204     FD = STDOUT_FILENO;
205     ShouldClose = false;
206     return;
207   }
208   
209   FD = open(Filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
210   if (FD < 0) {
211     ErrorInfo = "Error opening output file '" + std::string(Filename) + "'";
212     ShouldClose = false;
213   } else {
214     ShouldClose = true;
215   }
216 }
217
218 raw_fd_ostream::~raw_fd_ostream() {
219   flush();
220   if (ShouldClose)
221     close(FD);
222 }
223
224 void raw_fd_ostream::flush_impl() {
225   if (OutBufCur-OutBufStart)
226     ::write(FD, OutBufStart, OutBufCur-OutBufStart);
227   HandleFlush();
228 }
229
230 //===----------------------------------------------------------------------===//
231 //  raw_stdout/err_ostream
232 //===----------------------------------------------------------------------===//
233
234 raw_stdout_ostream::raw_stdout_ostream():raw_fd_ostream(STDOUT_FILENO, false) {}
235 raw_stderr_ostream::raw_stderr_ostream():raw_fd_ostream(STDERR_FILENO, false) {}
236
237 // An out of line virtual method to provide a home for the class vtable.
238 void raw_stdout_ostream::handle() {}
239 void raw_stderr_ostream::handle() {}
240
241 /// outs() - This returns a reference to a raw_ostream for standard output.
242 /// Use it like: outs() << "foo" << "bar";
243 raw_ostream &llvm::outs() {
244   static raw_stdout_ostream S;
245   return S;
246 }
247
248 /// errs() - This returns a reference to a raw_ostream for standard error.
249 /// Use it like: errs() << "foo" << "bar";
250 raw_ostream &llvm::errs() {
251   static raw_stderr_ostream S;
252   return S;
253 }
254
255 //===----------------------------------------------------------------------===//
256 //  raw_os_ostream
257 //===----------------------------------------------------------------------===//
258
259 raw_os_ostream::~raw_os_ostream() {
260   flush();
261 }
262
263 /// flush_impl - The is the piece of the class that is implemented by
264 /// subclasses.  This outputs the currently buffered data and resets the
265 /// buffer to empty.
266 void raw_os_ostream::flush_impl() {
267   if (OutBufCur-OutBufStart)
268     OS.write(OutBufStart, OutBufCur-OutBufStart);
269   HandleFlush();
270 }
271
272 //===----------------------------------------------------------------------===//
273 //  raw_string_ostream
274 //===----------------------------------------------------------------------===//
275
276 raw_string_ostream::~raw_string_ostream() {
277   flush();
278 }
279
280 /// flush_impl - The is the piece of the class that is implemented by
281 /// subclasses.  This outputs the currently buffered data and resets the
282 /// buffer to empty.
283 void raw_string_ostream::flush_impl() {
284   if (OutBufCur-OutBufStart)
285     OS.append(OutBufStart, OutBufCur-OutBufStart);
286   HandleFlush();
287 }
288
289 //===----------------------------------------------------------------------===//
290 //  raw_svector_ostream
291 //===----------------------------------------------------------------------===//
292
293 raw_svector_ostream::~raw_svector_ostream() {
294   flush();
295 }
296
297 /// flush_impl - The is the piece of the class that is implemented by
298 /// subclasses.  This outputs the currently buffered data and resets the
299 /// buffer to empty.
300 void raw_svector_ostream::flush_impl() {
301   if (OutBufCur-OutBufStart)
302     OS.append(OutBufStart, OutBufCur);
303   HandleFlush();
304 }
305