reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
//===-- llvm/Support/circular_raw_ostream.h - Buffered streams --*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains raw_ostream implementations for streams to do circular
// buffering of their output.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H
#define LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H

#include "llvm/Support/raw_ostream.h"

namespace llvm {
  /// circular_raw_ostream - A raw_ostream which *can* save its data
  /// to a circular buffer, or can pass it through directly to an
  /// underlying stream if specified with a buffer of zero.
  ///
  class circular_raw_ostream : public raw_ostream {
  public:
    /// TAKE_OWNERSHIP - Tell this stream that it owns the underlying
    /// stream and is responsible for cleanup, memory management
    /// issues, etc.
    ///
    static const bool TAKE_OWNERSHIP = true;

    /// REFERENCE_ONLY - Tell this stream it should not manage the
    /// held stream.
    ///
    static const bool REFERENCE_ONLY = false;

  private:
    /// TheStream - The real stream we output to. We set it to be
    /// unbuffered, since we're already doing our own buffering.
    ///
    raw_ostream *TheStream;

    /// OwnsStream - Are we responsible for managing the underlying
    /// stream?
    ///
    bool OwnsStream;

    /// BufferSize - The size of the buffer in bytes.
    ///
    size_t BufferSize;

    /// BufferArray - The actual buffer storage.
    ///
    char *BufferArray;

    /// Cur - Pointer to the current output point in BufferArray.
    ///
    char *Cur;

    /// Filled - Indicate whether the buffer has been completely
    /// filled.  This helps avoid garbage output.
    ///
    bool Filled;

    /// Banner - A pointer to a banner to print before dumping the
    /// log.
    ///
    const char *Banner;

    /// flushBuffer - Dump the contents of the buffer to Stream.
    ///
    void flushBuffer() {
      if (Filled)
        // Write the older portion of the buffer.
        TheStream->write(Cur, BufferArray + BufferSize - Cur);
      // Write the newer portion of the buffer.
      TheStream->write(BufferArray, Cur - BufferArray);
      Cur = BufferArray;
      Filled = false;
    }

    void write_impl(const char *Ptr, size_t Size) override;

    /// current_pos - Return the current position within the stream,
    /// not counting the bytes currently in the buffer.
    ///
    uint64_t current_pos() const override {
      // This has the same effect as calling TheStream.current_pos(),
      // but that interface is private.
      return TheStream->tell() - TheStream->GetNumBytesInBuffer();
    }

  public:
    /// circular_raw_ostream - Construct an optionally
    /// circular-buffered stream, handing it an underlying stream to
    /// do the "real" output.
    ///
    /// As a side effect, if BuffSize is nonzero, the given Stream is
    /// set to be Unbuffered.  This is because circular_raw_ostream
    /// does its own buffering, so it doesn't want another layer of
    /// buffering to be happening underneath it.
    ///
    /// "Owns" tells the circular_raw_ostream whether it is
    /// responsible for managing the held stream, doing memory
    /// management of it, etc.
    ///
    circular_raw_ostream(raw_ostream &Stream, const char *Header,
                         size_t BuffSize = 0, bool Owns = REFERENCE_ONLY)
        : raw_ostream(/*unbuffered*/ true), TheStream(nullptr),
          OwnsStream(Owns), BufferSize(BuffSize), BufferArray(nullptr),
          Filled(false), Banner(Header) {
      if (BufferSize != 0)
        BufferArray = new char[BufferSize];
      Cur = BufferArray;
      setStream(Stream, Owns);
    }

    ~circular_raw_ostream() override {
      flush();
      flushBufferWithBanner();
      releaseStream();
      delete[] BufferArray;
    }

    bool is_displayed() const override {
      return TheStream->is_displayed();
    }

    /// setStream - Tell the circular_raw_ostream to output a
    /// different stream.  "Owns" tells circular_raw_ostream whether
    /// it should take responsibility for managing the underlying
    /// stream.
    ///
    void setStream(raw_ostream &Stream, bool Owns = REFERENCE_ONLY) {
      releaseStream();
      TheStream = &Stream;
      OwnsStream = Owns;
    }

    /// flushBufferWithBanner - Force output of the buffer along with
    /// a small header.
    ///
    void flushBufferWithBanner();

  private:
    /// releaseStream - Delete the held stream if needed. Otherwise,
    /// transfer the buffer settings from this circular_raw_ostream
    /// back to the underlying stream.
    ///
    void releaseStream() {
      if (!TheStream)
        return;
      if (OwnsStream)
        delete TheStream;
    }
  };
} // end llvm namespace

#endif