LLVM API Documentation

raw_ostream.cpp

Go to the documentation of this file.
00001 //===--- raw_ostream.cpp - Implement the raw_ostream classes --------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This implements support for bulk buffered stream output.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "llvm/Support/raw_ostream.h"
00015 #include "llvm/Support/Format.h"
00016 #include "llvm/System/Program.h"
00017 #include "llvm/ADT/SmallVector.h"
00018 #include "llvm/Config/config.h"
00019 #include <ostream>
00020 
00021 #if defined(HAVE_UNISTD_H)
00022 # include <unistd.h>
00023 #endif
00024 #if defined(HAVE_FCNTL_H)
00025 # include <fcntl.h>
00026 #endif
00027 
00028 #if defined(_MSC_VER)
00029 #include <io.h>
00030 #include <fcntl.h>
00031 #ifndef STDIN_FILENO
00032 # define STDIN_FILENO 0
00033 #endif
00034 #ifndef STDOUT_FILENO
00035 # define STDOUT_FILENO 1
00036 #endif
00037 #ifndef STDERR_FILENO
00038 # define STDERR_FILENO 2
00039 #endif
00040 #endif
00041 
00042 using namespace llvm;
00043 
00044 
00045 // An out of line virtual method to provide a home for the class vtable.
00046 void raw_ostream::handle() {}
00047 
00048 raw_ostream &raw_ostream::operator<<(unsigned long N) {
00049   // Zero is a special case.
00050   if (N == 0)
00051     return *this << '0';
00052   
00053   char NumberBuffer[20];
00054   char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
00055   char *CurPtr = EndPtr;
00056   
00057   while (N) {
00058     *--CurPtr = '0' + char(N % 10);
00059     N /= 10;
00060   }
00061   return write(CurPtr, EndPtr-CurPtr);
00062 }
00063 
00064 raw_ostream &raw_ostream::operator<<(long N) {
00065   if (N <  0) {
00066     if (OutBufCur >= OutBufEnd)
00067       flush_impl();
00068     *OutBufCur++ = '-';
00069     
00070     N = -N;
00071   }
00072   
00073   return this->operator<<(static_cast<unsigned long>(N));
00074 }
00075 
00076 raw_ostream &raw_ostream::operator<<(unsigned long long N) {
00077   // Zero is a special case.
00078   if (N == 0)
00079     return *this << '0';
00080   
00081   char NumberBuffer[20];
00082   char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
00083   char *CurPtr = EndPtr;
00084   
00085   while (N) {
00086     *--CurPtr = '0' + char(N % 10);
00087     N /= 10;
00088   }
00089   return write(CurPtr, EndPtr-CurPtr);
00090 }
00091 
00092 raw_ostream &raw_ostream::operator<<(long long N) {
00093   if (N <  0) {
00094     if (OutBufCur >= OutBufEnd)
00095       flush_impl();
00096     *OutBufCur++ = '-';
00097     
00098     N = -N;
00099   }
00100   
00101   return this->operator<<(static_cast<unsigned long long>(N));
00102 }
00103 
00104 raw_ostream &raw_ostream::operator<<(const void *P) {
00105   // FIXME: This could be much faster if it matters.
00106   return *this << format("%p", P);
00107 }
00108 
00109 
00110 raw_ostream &raw_ostream::write(const char *Ptr, unsigned Size) {
00111   if (OutBufCur+Size > OutBufEnd)
00112     flush_impl();
00113   
00114   // Handle short strings specially, memcpy isn't very good at very short
00115   // strings.
00116   switch (Size) {
00117   case 4: OutBufCur[3] = Ptr[3]; // FALL THROUGH
00118   case 3: OutBufCur[2] = Ptr[2]; // FALL THROUGH
00119   case 2: OutBufCur[1] = Ptr[1]; // FALL THROUGH
00120   case 1: OutBufCur[0] = Ptr[0]; // FALL THROUGH
00121   case 0: break;
00122   default:
00123     // Normally the string to emit is shorter than the buffer.
00124     if (Size <= unsigned(OutBufEnd-OutBufStart)) {
00125       memcpy(OutBufCur, Ptr, Size);
00126       break;
00127     }
00128 
00129     // If emitting a string larger than our buffer, emit in chunks.  In this
00130     // case we know that we just flushed the buffer.
00131     while (Size) {
00132       unsigned NumToEmit = OutBufEnd-OutBufStart;
00133       if (Size < NumToEmit) NumToEmit = Size;
00134       assert(OutBufCur == OutBufStart);
00135       memcpy(OutBufStart, Ptr, NumToEmit);
00136       Ptr += NumToEmit;
00137       Size -= NumToEmit;
00138       OutBufCur = OutBufStart + NumToEmit;
00139       flush_impl();
00140     }
00141     break;
00142   }
00143   OutBufCur += Size;
00144   return *this;
00145 }
00146 
00147 // Formatted output.
00148 raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) {
00149   // If we have more than a few bytes left in our output buffer, try formatting
00150   // directly onto its end.
00151   unsigned NextBufferSize = 127;
00152   if (OutBufEnd-OutBufCur > 3) {
00153     unsigned BufferBytesLeft = OutBufEnd-OutBufCur;
00154     unsigned BytesUsed = Fmt.print(OutBufCur, BufferBytesLeft);
00155     
00156     // Common case is that we have plenty of space.
00157     if (BytesUsed < BufferBytesLeft) {
00158       OutBufCur += BytesUsed;
00159       return *this;
00160     }
00161     
00162     // Otherwise, we overflowed and the return value tells us the size to try
00163     // again with.
00164     NextBufferSize = BytesUsed;
00165   }
00166   
00167   // If we got here, we didn't have enough space in the output buffer for the
00168   // string.  Try printing into a SmallVector that is resized to have enough
00169   // space.  Iterate until we win.
00170   SmallVector<char, 128> V;
00171   
00172   while (1) {
00173     V.resize(NextBufferSize);
00174     
00175     // Try formatting into the SmallVector.
00176     unsigned BytesUsed = Fmt.print(&V[0], NextBufferSize);
00177     
00178     // If BytesUsed fit into the vector, we win.
00179     if (BytesUsed <= NextBufferSize)
00180       return write(&V[0], BytesUsed);
00181     
00182     // Otherwise, try again with a new size.
00183     assert(BytesUsed > NextBufferSize && "Didn't grow buffer!?");
00184     NextBufferSize = BytesUsed;
00185   }
00186 }
00187 
00188 //===----------------------------------------------------------------------===//
00189 //  Formatted Output
00190 //===----------------------------------------------------------------------===//
00191 
00192 // Out of line virtual method.
00193 void format_object_base::home() {
00194 }
00195 
00196 //===----------------------------------------------------------------------===//
00197 //  raw_fd_ostream
00198 //===----------------------------------------------------------------------===//
00199 
00200 /// raw_fd_ostream - Open the specified file for writing. If an error
00201 /// occurs, information about the error is put into ErrorInfo, and the
00202 /// stream should be immediately destroyed; the string will be empty
00203 /// if no error occurred.
00204 raw_fd_ostream::raw_fd_ostream(const char *Filename, bool Binary,
00205                                std::string &ErrorInfo) {
00206   ErrorInfo.clear();
00207 
00208   // Handle "-" as stdout.
00209   if (Filename[0] == '-' && Filename[1] == 0) {
00210     FD = STDOUT_FILENO;
00211     // If user requested binary then put stdout into binary mode if
00212     // possible.
00213     if (Binary)
00214       sys::Program::ChangeStdoutToBinary();
00215     ShouldClose = false;
00216     return;
00217   }
00218   
00219   int Flags = O_WRONLY|O_CREAT|O_TRUNC;
00220 #ifdef O_BINARY
00221   if (Binary)
00222     Flags |= O_BINARY;
00223 #endif
00224   FD = open(Filename, Flags, 0644);
00225   if (FD < 0) {
00226     ErrorInfo = "Error opening output file '" + std::string(Filename) + "'";
00227     ShouldClose = false;
00228   } else {
00229     ShouldClose = true;
00230   }
00231 }
00232 
00233 raw_fd_ostream::~raw_fd_ostream() {
00234   if (FD >= 0) {
00235     flush();
00236     if (ShouldClose)
00237       ::close(FD);
00238   }
00239 }
00240 
00241 void raw_fd_ostream::flush_impl() {
00242   assert (FD >= 0 && "File already closed.");
00243   if (OutBufCur-OutBufStart)
00244     ::write(FD, OutBufStart, OutBufCur-OutBufStart);
00245   HandleFlush();
00246 }
00247 
00248 void raw_fd_ostream::close() {
00249   assert (ShouldClose);
00250   ShouldClose = false;
00251   flush();
00252   ::close(FD);
00253   FD = -1;
00254 }
00255 
00256 uint64_t raw_fd_ostream::tell() {
00257   // We have to take into account the bytes waiting in the buffer.  For now
00258   // we do the easy thing and just flush the buffer before getting the
00259   // current file offset.
00260   flush();  
00261   return (uint64_t) lseek(FD, 0, SEEK_CUR);
00262 }
00263 
00264 //===----------------------------------------------------------------------===//
00265 //  raw_stdout/err_ostream
00266 //===----------------------------------------------------------------------===//
00267 
00268 raw_stdout_ostream::raw_stdout_ostream():raw_fd_ostream(STDOUT_FILENO, false) {}
00269 raw_stderr_ostream::raw_stderr_ostream():raw_fd_ostream(STDERR_FILENO, false) {}
00270 
00271 // An out of line virtual method to provide a home for the class vtable.
00272 void raw_stdout_ostream::handle() {}
00273 void raw_stderr_ostream::handle() {}
00274 
00275 /// outs() - This returns a reference to a raw_ostream for standard output.
00276 /// Use it like: outs() << "foo" << "bar";
00277 raw_ostream &llvm::outs() {
00278   static raw_stdout_ostream S;
00279   return S;
00280 }
00281 
00282 /// errs() - This returns a reference to a raw_ostream for standard error.
00283 /// Use it like: errs() << "foo" << "bar";
00284 raw_ostream &llvm::errs() {
00285   static raw_stderr_ostream S;
00286   return S;
00287 }
00288 
00289 //===----------------------------------------------------------------------===//
00290 //  raw_os_ostream
00291 //===----------------------------------------------------------------------===//
00292 
00293 raw_os_ostream::~raw_os_ostream() {
00294   flush();
00295 }
00296 
00297 /// flush_impl - The is the piece of the class that is implemented by
00298 /// subclasses.  This outputs the currently buffered data and resets the
00299 /// buffer to empty.
00300 void raw_os_ostream::flush_impl() {
00301   if (OutBufCur-OutBufStart)
00302     OS.write(OutBufStart, OutBufCur-OutBufStart);
00303   HandleFlush();
00304 }
00305 
00306 //===----------------------------------------------------------------------===//
00307 //  raw_string_ostream
00308 //===----------------------------------------------------------------------===//
00309 
00310 raw_string_ostream::~raw_string_ostream() {
00311   flush();
00312 }
00313 
00314 /// flush_impl - The is the piece of the class that is implemented by
00315 /// subclasses.  This outputs the currently buffered data and resets the
00316 /// buffer to empty.
00317 void raw_string_ostream::flush_impl() {
00318   if (OutBufCur-OutBufStart)
00319     OS.append(OutBufStart, OutBufCur-OutBufStart);
00320   HandleFlush();
00321 }
00322 
00323 //===----------------------------------------------------------------------===//
00324 //  raw_svector_ostream
00325 //===----------------------------------------------------------------------===//
00326 
00327 raw_svector_ostream::~raw_svector_ostream() {
00328   flush();
00329 }
00330 
00331 /// flush_impl - The is the piece of the class that is implemented by
00332 /// subclasses.  This outputs the currently buffered data and resets the
00333 /// buffer to empty.
00334 void raw_svector_ostream::flush_impl() {
00335   if (OutBufCur-OutBufStart)
00336     OS.append(OutBufStart, OutBufCur);
00337   HandleFlush();
00338 }
00339 



This web site is hosted by the Computer Science Department at the University of Illinois at Urbana-Champaign.