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