mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-09-08 23:55:03 +00:00
raw_ostream: Add the capability for subclasses to manually install an external
buffer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79382 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
db8dc2b9fa
commit
906d5b4455
@ -42,12 +42,25 @@ private:
|
|||||||
/// need to take the slow path to write a single character.
|
/// need to take the slow path to write a single character.
|
||||||
///
|
///
|
||||||
/// The buffer is in one of three states:
|
/// The buffer is in one of three states:
|
||||||
/// 1. Unbuffered (Unbuffered == true)
|
/// 1. Unbuffered (BufferMode == Unbuffered)
|
||||||
/// 1. Uninitialized (Unbuffered == false && OutBufStart == 0).
|
/// 1. Uninitialized (BufferMode != Unbuffered && OutBufStart == 0).
|
||||||
/// 2. Buffered (Unbuffered == false && OutBufStart != 0 &&
|
/// 2. Buffered (BufferMode != Unbuffered && OutBufStart != 0 &&
|
||||||
/// OutBufEnd - OutBufStart >= 64).
|
/// OutBufEnd - OutBufStart >= 64).
|
||||||
|
///
|
||||||
|
/// If buffered, then the raw_ostream owns the buffer if (BufferMode ==
|
||||||
|
/// InternalBuffer); otherwise the buffer has been set via SetBuffer and is
|
||||||
|
/// managed by the subclass.
|
||||||
|
///
|
||||||
|
/// If a subclass installs an external buffer using SetBuffer then it can wait
|
||||||
|
/// for a \see write_impl() call to handle the data which has been put into
|
||||||
|
/// this buffer.
|
||||||
char *OutBufStart, *OutBufEnd, *OutBufCur;
|
char *OutBufStart, *OutBufEnd, *OutBufCur;
|
||||||
bool Unbuffered;
|
|
||||||
|
enum BufferKind {
|
||||||
|
Unbuffered = 0,
|
||||||
|
InternalBuffer,
|
||||||
|
ExternalBuffer
|
||||||
|
} BufferMode;
|
||||||
|
|
||||||
/// Error This flag is true if an error of any kind has been detected.
|
/// Error This flag is true if an error of any kind has been detected.
|
||||||
///
|
///
|
||||||
@ -68,7 +81,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
explicit raw_ostream(bool unbuffered=false)
|
explicit raw_ostream(bool unbuffered=false)
|
||||||
: Unbuffered(unbuffered), Error(false) {
|
: BufferMode(unbuffered ? Unbuffered : InternalBuffer), Error(false) {
|
||||||
// Start out ready to flush.
|
// Start out ready to flush.
|
||||||
OutBufStart = OutBufEnd = OutBufCur = 0;
|
OutBufStart = OutBufEnd = OutBufCur = 0;
|
||||||
}
|
}
|
||||||
@ -100,9 +113,12 @@ public:
|
|||||||
/// determined buffer size.
|
/// determined buffer size.
|
||||||
void SetBuffered();
|
void SetBuffered();
|
||||||
|
|
||||||
/// SetBufferrSize - Set the stream to be buffered, using the
|
/// SetBufferSize - Set the stream to be buffered, using the
|
||||||
/// specified buffer size.
|
/// specified buffer size.
|
||||||
void SetBufferSize(size_t Size);
|
void SetBufferSize(size_t Size) {
|
||||||
|
flush();
|
||||||
|
SetBufferAndMode(new char[Size], Size, InternalBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
size_t GetBufferSize() {
|
size_t GetBufferSize() {
|
||||||
// If we're supposed to be buffered but haven't actually gotten around
|
// If we're supposed to be buffered but haven't actually gotten around
|
||||||
@ -118,7 +134,10 @@ public:
|
|||||||
/// unbuffered, the stream will flush after every write. This routine
|
/// unbuffered, the stream will flush after every write. This routine
|
||||||
/// will also flush the buffer immediately when the stream is being
|
/// will also flush the buffer immediately when the stream is being
|
||||||
/// set to unbuffered.
|
/// set to unbuffered.
|
||||||
void SetUnbuffered();
|
void SetUnbuffered() {
|
||||||
|
flush();
|
||||||
|
SetBufferAndMode(0, 0, Unbuffered);
|
||||||
|
}
|
||||||
|
|
||||||
size_t GetNumBytesInBuffer() const {
|
size_t GetNumBytesInBuffer() const {
|
||||||
return OutBufCur - OutBufStart;
|
return OutBufCur - OutBufStart;
|
||||||
@ -175,7 +194,9 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
raw_ostream &operator<<(const std::string& Str) {
|
raw_ostream &operator<<(const std::string &Str) {
|
||||||
|
// Avoid the fast path, it would only increase code size for a marginal win.
|
||||||
|
|
||||||
write(Str.data(), Str.length());
|
write(Str.data(), Str.length());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -232,6 +253,13 @@ private:
|
|||||||
/// by subclasses. This writes the \args Size bytes starting at
|
/// by subclasses. This writes the \args Size bytes starting at
|
||||||
/// \arg Ptr to the underlying stream.
|
/// \arg Ptr to the underlying stream.
|
||||||
///
|
///
|
||||||
|
/// This function is guaranteed to only be called at a point at which it is
|
||||||
|
/// safe for the subclass to install a new buffer via SetBuffer.
|
||||||
|
///
|
||||||
|
/// \arg Ptr - The start of the data to be written. For buffered streams this
|
||||||
|
/// is guaranteed to be the start of the buffer.
|
||||||
|
/// \arg Size - The number of bytes to be written.
|
||||||
|
///
|
||||||
/// \invariant { Size > 0 }
|
/// \invariant { Size > 0 }
|
||||||
virtual void write_impl(const char *Ptr, size_t Size) = 0;
|
virtual void write_impl(const char *Ptr, size_t Size) = 0;
|
||||||
|
|
||||||
@ -243,6 +271,14 @@ private:
|
|||||||
virtual uint64_t current_pos() = 0;
|
virtual uint64_t current_pos() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/// SetBuffer - Use the provided buffer as the raw_ostream buffer. This is
|
||||||
|
/// intended for use only by subclasses which can arrange for the output to go
|
||||||
|
/// directly into the desired output buffer, instead of being copied on each
|
||||||
|
/// flush.
|
||||||
|
void SetBuffer(char *BufferStart, size_t Size) {
|
||||||
|
SetBufferAndMode(BufferStart, Size, ExternalBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
/// preferred_buffer_size - Return an efficient buffer size for the
|
/// preferred_buffer_size - Return an efficient buffer size for the
|
||||||
/// underlying output mechanism.
|
/// underlying output mechanism.
|
||||||
virtual size_t preferred_buffer_size();
|
virtual size_t preferred_buffer_size();
|
||||||
@ -259,6 +295,9 @@ protected:
|
|||||||
// Private Interface
|
// Private Interface
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
private:
|
private:
|
||||||
|
/// SetBufferAndMode - Install the given buffer and mode.
|
||||||
|
void SetBufferAndMode(char *BufferStart, size_t Size, BufferKind Mode);
|
||||||
|
|
||||||
/// flush_nonempty - Flush the current buffer, which is known to be
|
/// flush_nonempty - Flush the current buffer, which is known to be
|
||||||
/// non-empty. This outputs the currently buffered data and resets
|
/// non-empty. This outputs the currently buffered data and resets
|
||||||
/// the buffer to empty.
|
/// the buffer to empty.
|
||||||
@ -422,7 +461,7 @@ class raw_svector_ostream : public raw_ostream {
|
|||||||
/// counting the bytes currently in the buffer.
|
/// counting the bytes currently in the buffer.
|
||||||
virtual uint64_t current_pos();
|
virtual uint64_t current_pos();
|
||||||
public:
|
public:
|
||||||
explicit raw_svector_ostream(SmallVectorImpl<char> &O) : OS(O) {}
|
explicit raw_svector_ostream(SmallVectorImpl<char> &O);
|
||||||
~raw_svector_ostream();
|
~raw_svector_ostream();
|
||||||
|
|
||||||
/// tell - Return the current offset with the stream.
|
/// tell - Return the current offset with the stream.
|
||||||
|
@ -52,7 +52,8 @@ raw_ostream::~raw_ostream() {
|
|||||||
assert(OutBufCur == OutBufStart &&
|
assert(OutBufCur == OutBufStart &&
|
||||||
"raw_ostream destructor called with non-empty buffer!");
|
"raw_ostream destructor called with non-empty buffer!");
|
||||||
|
|
||||||
delete [] OutBufStart;
|
if (BufferMode == InternalBuffer)
|
||||||
|
delete [] OutBufStart;
|
||||||
|
|
||||||
// If there are any pending errors, report them now. Clients wishing
|
// If there are any pending errors, report them now. Clients wishing
|
||||||
// to avoid llvm_report_error calls should check for errors with
|
// to avoid llvm_report_error calls should check for errors with
|
||||||
@ -79,24 +80,21 @@ void raw_ostream::SetBuffered() {
|
|||||||
SetUnbuffered();
|
SetUnbuffered();
|
||||||
}
|
}
|
||||||
|
|
||||||
void raw_ostream::SetBufferSize(size_t Size) {
|
void raw_ostream::SetBufferAndMode(char *BufferStart, size_t Size,
|
||||||
assert(Size >= 64 &&
|
BufferKind Mode) {
|
||||||
"Buffer size must be somewhat large for invariants to hold");
|
assert(((Mode == Unbuffered && BufferStart == 0 && Size == 0) ||
|
||||||
flush();
|
(Mode != Unbuffered && BufferStart && Size >= 64)) &&
|
||||||
|
"stream must be unbuffered, or have >= 64 bytes of buffer");
|
||||||
|
// Make sure the current buffer is free of content (we can't flush here; the
|
||||||
|
// child buffer management logic will be in write_impl).
|
||||||
|
assert(GetNumBytesInBuffer() == 0 && "Current buffer is non-empty!");
|
||||||
|
|
||||||
delete [] OutBufStart;
|
if (BufferMode == InternalBuffer)
|
||||||
OutBufStart = new char[Size];
|
delete [] OutBufStart;
|
||||||
|
OutBufStart = BufferStart;
|
||||||
OutBufEnd = OutBufStart+Size;
|
OutBufEnd = OutBufStart+Size;
|
||||||
OutBufCur = OutBufStart;
|
OutBufCur = OutBufStart;
|
||||||
Unbuffered = false;
|
BufferMode = Mode;
|
||||||
}
|
|
||||||
|
|
||||||
void raw_ostream::SetUnbuffered() {
|
|
||||||
flush();
|
|
||||||
|
|
||||||
delete [] OutBufStart;
|
|
||||||
OutBufStart = OutBufEnd = OutBufCur = 0;
|
|
||||||
Unbuffered = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
raw_ostream &raw_ostream::operator<<(unsigned long N) {
|
raw_ostream &raw_ostream::operator<<(unsigned long N) {
|
||||||
@ -180,14 +178,15 @@ raw_ostream &raw_ostream::operator<<(const void *P) {
|
|||||||
|
|
||||||
void raw_ostream::flush_nonempty() {
|
void raw_ostream::flush_nonempty() {
|
||||||
assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty.");
|
assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty.");
|
||||||
write_impl(OutBufStart, OutBufCur - OutBufStart);
|
size_t Length = OutBufCur - OutBufStart;
|
||||||
OutBufCur = OutBufStart;
|
OutBufCur = OutBufStart;
|
||||||
|
write_impl(OutBufStart, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
raw_ostream &raw_ostream::write(unsigned char C) {
|
raw_ostream &raw_ostream::write(unsigned char C) {
|
||||||
// Group exceptional cases into a single branch.
|
// Group exceptional cases into a single branch.
|
||||||
if (OutBufCur >= OutBufEnd) {
|
if (OutBufCur >= OutBufEnd) {
|
||||||
if (Unbuffered) {
|
if (BufferMode == Unbuffered) {
|
||||||
write_impl(reinterpret_cast<char*>(&C), 1);
|
write_impl(reinterpret_cast<char*>(&C), 1);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -198,7 +197,7 @@ raw_ostream &raw_ostream::write(unsigned char C) {
|
|||||||
SetBuffered();
|
SetBuffered();
|
||||||
// It's possible for the underlying stream to decline
|
// It's possible for the underlying stream to decline
|
||||||
// buffering, so check this condition again.
|
// buffering, so check this condition again.
|
||||||
if (Unbuffered) {
|
if (BufferMode == Unbuffered) {
|
||||||
write_impl(reinterpret_cast<char*>(&C), 1);
|
write_impl(reinterpret_cast<char*>(&C), 1);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -213,7 +212,7 @@ raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) {
|
|||||||
// Group exceptional cases into a single branch.
|
// Group exceptional cases into a single branch.
|
||||||
if (BUILTIN_EXPECT(OutBufCur+Size > OutBufEnd, false)) {
|
if (BUILTIN_EXPECT(OutBufCur+Size > OutBufEnd, false)) {
|
||||||
if (BUILTIN_EXPECT(!OutBufStart, false)) {
|
if (BUILTIN_EXPECT(!OutBufStart, false)) {
|
||||||
if (Unbuffered) {
|
if (BufferMode == Unbuffered) {
|
||||||
write_impl(Ptr, Size);
|
write_impl(Ptr, Size);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -498,6 +497,9 @@ void raw_string_ostream::write_impl(const char *Ptr, size_t Size) {
|
|||||||
// raw_svector_ostream
|
// raw_svector_ostream
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
raw_svector_ostream::raw_svector_ostream(SmallVectorImpl<char> &O) : OS(O) {
|
||||||
|
}
|
||||||
|
|
||||||
raw_svector_ostream::~raw_svector_ostream() {
|
raw_svector_ostream::~raw_svector_ostream() {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user