1 //===--- raw_ostream.cpp - Implement the raw_ostream classes --------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This implements support for bulk buffered stream output.
12 //===----------------------------------------------------------------------===//
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"
20 #if defined(HAVE_UNISTD_H)
23 #if defined(HAVE_FCNTL_H)
30 # define STDIN_FILENO 0
33 # define STDOUT_FILENO 1
36 # define STDERR_FILENO 2
43 // An out of line virtual method to provide a home for the class vtable.
44 void raw_ostream::handle() {}
46 raw_ostream &raw_ostream::operator<<(unsigned long N) {
47 // Zero is a special case.
51 char NumberBuffer[20];
52 char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
53 char *CurPtr = EndPtr;
56 *--CurPtr = '0' + char(N % 10);
59 return write(CurPtr, EndPtr-CurPtr);
62 raw_ostream &raw_ostream::operator<<(long N) {
64 if (OutBufCur >= OutBufEnd)
71 return this->operator<<(static_cast<unsigned long>(N));
74 raw_ostream &raw_ostream::operator<<(unsigned long long N) {
75 // Zero is a special case.
79 char NumberBuffer[20];
80 char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
81 char *CurPtr = EndPtr;
84 *--CurPtr = '0' + char(N % 10);
87 return write(CurPtr, EndPtr-CurPtr);
90 raw_ostream &raw_ostream::operator<<(long long N) {
92 if (OutBufCur >= OutBufEnd)
99 return this->operator<<(static_cast<unsigned long long>(N));
102 raw_ostream &raw_ostream::write(const char *Ptr, unsigned Size) {
103 if (OutBufCur+Size > OutBufEnd)
106 // Handle short strings specially, memcpy isn't very good at very short
109 case 4: OutBufCur[3] = Ptr[3]; // FALL THROUGH
110 case 3: OutBufCur[2] = Ptr[2]; // FALL THROUGH
111 case 2: OutBufCur[1] = Ptr[1]; // FALL THROUGH
112 case 1: OutBufCur[0] = Ptr[0]; // FALL THROUGH
115 // Normally the string to emit is shorter than the buffer.
116 if (Size <= unsigned(OutBufEnd-OutBufStart)) {
117 memcpy(OutBufCur, Ptr, Size);
121 // If emitting a string larger than our buffer, emit in chunks. In this
122 // case we know that we just flushed the buffer.
124 unsigned NumToEmit = OutBufEnd-OutBufStart;
125 if (Size < NumToEmit) NumToEmit = Size;
126 assert(OutBufCur == OutBufStart);
127 memcpy(OutBufStart, Ptr, NumToEmit);
130 OutBufCur = OutBufStart + NumToEmit;
140 raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) {
141 // If we have more than a few bytes left in our output buffer, try formatting
142 // directly onto its end.
143 unsigned NextBufferSize = 127;
144 if (OutBufEnd-OutBufCur > 3) {
145 unsigned BufferBytesLeft = OutBufEnd-OutBufCur;
146 unsigned BytesUsed = Fmt.print(OutBufCur, BufferBytesLeft);
148 // Common case is that we have plenty of space.
149 if (BytesUsed < BufferBytesLeft) {
150 OutBufCur += BytesUsed;
154 // Otherwise, we overflowed and the return value tells us the size to try
156 NextBufferSize = BytesUsed;
159 // If we got here, we didn't have enough space in the output buffer for the
160 // string. Try printing into a SmallVector that is resized to have enough
161 // space. Iterate until we win.
162 SmallVector<char, 128> V;
165 V.resize(NextBufferSize);
167 // Try formatting into the SmallVector.
168 unsigned BytesUsed = Fmt.print(&V[0], NextBufferSize);
170 // If BytesUsed fit into the vector, we win.
171 if (BytesUsed < NextBufferSize)
172 return write(&V[0], BytesUsed);
174 // Otherwise, try again with a new size.
175 assert(BytesUsed > NextBufferSize && "Didn't grow buffer!?");
176 NextBufferSize = BytesUsed;
180 //===----------------------------------------------------------------------===//
182 //===----------------------------------------------------------------------===//
184 // Out of line virtual method.
185 void format_object_base::home() {
188 //===----------------------------------------------------------------------===//
190 //===----------------------------------------------------------------------===//
192 /// raw_fd_ostream - Open the specified file for writing. If an error occurs,
193 /// information about the error is put into ErrorInfo, and the stream should
194 /// be immediately destroyed.
195 raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo) {
196 // Handle "-" as stdout.
197 if (Filename[0] == '-' && Filename[1] == 0) {
203 FD = open(Filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
205 ErrorInfo = "Error opening output file '" + std::string(Filename) + "'";
212 raw_fd_ostream::~raw_fd_ostream() {
218 void raw_fd_ostream::flush_impl() {
219 if (OutBufCur-OutBufStart)
220 ::write(FD, OutBufStart, OutBufCur-OutBufStart);
224 //===----------------------------------------------------------------------===//
225 // raw_stdout/err_ostream
226 //===----------------------------------------------------------------------===//
228 raw_stdout_ostream::raw_stdout_ostream():raw_fd_ostream(STDOUT_FILENO, false) {}
229 raw_stderr_ostream::raw_stderr_ostream():raw_fd_ostream(STDERR_FILENO, false) {}
231 // An out of line virtual method to provide a home for the class vtable.
232 void raw_stdout_ostream::handle() {}
233 void raw_stderr_ostream::handle() {}
235 /// outs() - This returns a reference to a raw_ostream for standard output.
236 /// Use it like: outs() << "foo" << "bar";
237 raw_ostream &llvm::outs() {
238 static raw_stdout_ostream S;
242 /// errs() - This returns a reference to a raw_ostream for standard error.
243 /// Use it like: errs() << "foo" << "bar";
244 raw_ostream &llvm::errs() {
245 static raw_stderr_ostream S;
249 //===----------------------------------------------------------------------===//
251 //===----------------------------------------------------------------------===//
253 /// flush_impl - The is the piece of the class that is implemented by
254 /// subclasses. This outputs the currently buffered data and resets the
256 void raw_os_ostream::flush_impl() {
257 if (OutBufCur-OutBufStart)
258 OS.write(OutBufStart, OutBufCur-OutBufStart);