LLVM API Documentation

circular_raw_ostream.h
Go to the documentation of this file.
00001 //===-- llvm/Support/circular_raw_ostream.h - Buffered streams --*- C++ -*-===//
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 file contains raw_ostream implementations for streams to do circular
00011 // buffering of their output.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #ifndef LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H
00016 #define LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H
00017 
00018 #include "llvm/Support/raw_ostream.h"
00019 
00020 namespace llvm 
00021 {
00022   /// circular_raw_ostream - A raw_ostream which *can* save its data
00023   /// to a circular buffer, or can pass it through directly to an
00024   /// underlying stream if specified with a buffer of zero.
00025   ///
00026   class circular_raw_ostream : public raw_ostream {
00027   public:
00028     /// TAKE_OWNERSHIP - Tell this stream that it owns the underlying
00029     /// stream and is responsible for cleanup, memory management
00030     /// issues, etc.
00031     ///
00032     static const bool TAKE_OWNERSHIP = true;
00033 
00034     /// REFERENCE_ONLY - Tell this stream it should not manage the
00035     /// held stream.
00036     ///
00037     static const bool REFERENCE_ONLY = false;
00038 
00039   private:
00040     /// TheStream - The real stream we output to. We set it to be
00041     /// unbuffered, since we're already doing our own buffering.
00042     ///
00043     raw_ostream *TheStream;
00044 
00045     /// OwnsStream - Are we responsible for managing the underlying
00046     /// stream?
00047     ///
00048     bool OwnsStream;
00049 
00050     /// BufferSize - The size of the buffer in bytes.
00051     ///
00052     size_t BufferSize;
00053 
00054     /// BufferArray - The actual buffer storage.
00055     ///
00056     char *BufferArray;
00057 
00058     /// Cur - Pointer to the current output point in BufferArray.
00059     ///
00060     char *Cur;
00061 
00062     /// Filled - Indicate whether the buffer has been completely
00063     /// filled.  This helps avoid garbage output.
00064     ///
00065     bool Filled;
00066 
00067     /// Banner - A pointer to a banner to print before dumping the
00068     /// log.
00069     ///
00070     const char *Banner;
00071 
00072     /// flushBuffer - Dump the contents of the buffer to Stream.
00073     ///
00074     void flushBuffer() {
00075       if (Filled)
00076         // Write the older portion of the buffer.
00077         TheStream->write(Cur, BufferArray + BufferSize - Cur);
00078       // Write the newer portion of the buffer.
00079       TheStream->write(BufferArray, Cur - BufferArray);
00080       Cur = BufferArray;
00081       Filled = false;
00082     }
00083 
00084     void write_impl(const char *Ptr, size_t Size) override;
00085 
00086     /// current_pos - Return the current position within the stream,
00087     /// not counting the bytes currently in the buffer.
00088     ///
00089     uint64_t current_pos() const override {
00090       // This has the same effect as calling TheStream.current_pos(),
00091       // but that interface is private.
00092       return TheStream->tell() - TheStream->GetNumBytesInBuffer();
00093     }
00094 
00095   public:
00096     /// circular_raw_ostream - Construct an optionally
00097     /// circular-buffered stream, handing it an underlying stream to
00098     /// do the "real" output.
00099     ///
00100     /// As a side effect, if BuffSize is nonzero, the given Stream is
00101     /// set to be Unbuffered.  This is because circular_raw_ostream
00102     /// does its own buffering, so it doesn't want another layer of
00103     /// buffering to be happening underneath it.
00104     ///
00105     /// "Owns" tells the circular_raw_ostream whether it is
00106     /// responsible for managing the held stream, doing memory
00107     /// management of it, etc.
00108     ///
00109     circular_raw_ostream(raw_ostream &Stream, const char *Header,
00110                          size_t BuffSize = 0, bool Owns = REFERENCE_ONLY) 
00111         : raw_ostream(/*unbuffered*/true),
00112             TheStream(nullptr),
00113             OwnsStream(Owns),
00114             BufferSize(BuffSize),
00115             BufferArray(nullptr),
00116             Filled(false),
00117             Banner(Header) {
00118       if (BufferSize != 0)
00119         BufferArray = new char[BufferSize];
00120       Cur = BufferArray;
00121       setStream(Stream, Owns);
00122     }
00123     explicit circular_raw_ostream()
00124         : raw_ostream(/*unbuffered*/true),
00125             TheStream(nullptr),
00126             OwnsStream(REFERENCE_ONLY),
00127             BufferArray(nullptr),
00128             Filled(false),
00129             Banner("") {
00130       Cur = BufferArray;
00131     }
00132 
00133     ~circular_raw_ostream() {
00134       flush();
00135       flushBufferWithBanner();
00136       releaseStream();
00137       delete[] BufferArray;
00138     }
00139 
00140     /// setStream - Tell the circular_raw_ostream to output a
00141     /// different stream.  "Owns" tells circular_raw_ostream whether
00142     /// it should take responsibility for managing the underlying
00143     /// stream.
00144     ///
00145     void setStream(raw_ostream &Stream, bool Owns = REFERENCE_ONLY) {
00146       releaseStream();
00147       TheStream = &Stream;
00148       OwnsStream = Owns;
00149     }
00150 
00151     /// flushBufferWithBanner - Force output of the buffer along with
00152     /// a small header.
00153     ///
00154     void flushBufferWithBanner();
00155 
00156   private:
00157     /// releaseStream - Delete the held stream if needed. Otherwise,
00158     /// transfer the buffer settings from this circular_raw_ostream
00159     /// back to the underlying stream.
00160     ///
00161     void releaseStream() {
00162       if (!TheStream)
00163         return;
00164       if (OwnsStream)
00165         delete TheStream;
00166     }
00167   };
00168 } // end llvm namespace
00169 
00170 
00171 #endif