mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 00:32:55 +00:00
add a simple mechanism for formatted output. This gives raw_ostream's
all the power and risk of fprintf format strings. Use them like this: OS << format("%10.4f", 42.0) << "\n" << format("%x", 42) << '\n'; git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@55246 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8ff7ce3dd2
commit
097af7fc8f
@ -21,7 +21,8 @@
|
||||
#include <iosfwd>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class format_object_base;
|
||||
|
||||
/// raw_ostream - This class implements an extremely fast bulk output stream
|
||||
/// that can *only* output to a stream. It does not support seeking, reopening,
|
||||
/// rewinding, line buffered disciplines etc. It is a simple buffer that outputs
|
||||
@ -92,11 +93,8 @@ public:
|
||||
}
|
||||
|
||||
raw_ostream &operator<<(unsigned long N);
|
||||
|
||||
raw_ostream &operator<<(long N);
|
||||
|
||||
raw_ostream &operator<<(unsigned long long N);
|
||||
|
||||
raw_ostream &operator<<(long long N);
|
||||
|
||||
raw_ostream &operator<<(unsigned int N) {
|
||||
@ -111,9 +109,11 @@ public:
|
||||
return this->operator<<(ftostr(N));
|
||||
}
|
||||
|
||||
|
||||
raw_ostream &write(const char *Ptr, unsigned Size);
|
||||
|
||||
// Formatted output, see the format() function below.
|
||||
raw_ostream &operator<<(const format_object_base &Fmt);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Subclass Interface
|
||||
//===--------------------------------------------------------------------===//
|
||||
@ -137,6 +137,63 @@ private:
|
||||
virtual void handle();
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Formatted Output
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// format_object_base - This is a helper class used for handling formatted
|
||||
/// output. It is the abstract base class of a templated derived class.
|
||||
class format_object_base {
|
||||
protected:
|
||||
const char *Fmt;
|
||||
virtual void home(); // Out of line virtual method.
|
||||
public:
|
||||
format_object_base(const char *fmt) : Fmt(fmt) {}
|
||||
virtual ~format_object_base() {}
|
||||
|
||||
/// print - Format the object into the specified buffer. On success, this
|
||||
/// returns the length of the formatted string. If the buffer is too small,
|
||||
/// this returns a length to retry with, which will be larger than BufferSize.
|
||||
virtual unsigned print(char *Buffer, unsigned BufferSize) const = 0;
|
||||
};
|
||||
|
||||
/// format_object - This is a templated helper class used by the format function
|
||||
/// that captures the object to be formated and the format string. When
|
||||
/// actually printed, this synthesizes the string into a temporary buffer
|
||||
/// provided and returns whether or not it is big enough.
|
||||
template <typename T>
|
||||
class format_object : public format_object_base {
|
||||
T Val;
|
||||
public:
|
||||
format_object(const char *fmt, const T &val)
|
||||
: format_object_base(fmt), Val(val) {
|
||||
}
|
||||
|
||||
/// print - Format the object into the specified buffer. On success, this
|
||||
/// returns the length of the formatted string. If the buffer is too small,
|
||||
/// this returns a length to retry with, which will be larger than BufferSize.
|
||||
virtual unsigned print(char *Buffer, unsigned BufferSize) const {
|
||||
int N = snprintf(Buffer, BufferSize-1, Fmt, Val);
|
||||
if (N < 0) // VC++ and old GlibC return negative on overflow.
|
||||
return BufferSize*2;
|
||||
if (unsigned(N) >= BufferSize-1)// Other impls yield number of bytes needed.
|
||||
return N+1;
|
||||
// If N is positive and <= BufferSize-1, then the string fit, yay.
|
||||
return N;
|
||||
}
|
||||
};
|
||||
|
||||
/// format - This is a helper function that is used to produce formatted output.
|
||||
/// This is typically used like: OS << format("%0.4f", myfloat) << '\n';
|
||||
template <typename T>
|
||||
inline format_object<T> format(const char *Fmt, const T &Val) {
|
||||
return format_object<T>(Fmt, Val);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// File Output Streams
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// raw_fd_ostream - A raw_ostream that writes to a file descriptor.
|
||||
///
|
||||
class raw_fd_ostream : public raw_ostream {
|
||||
@ -187,6 +244,10 @@ raw_ostream &outs();
|
||||
raw_ostream &errs();
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Bridge Output Streams
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// raw_os_ostream - A raw_ostream that writes to an std::ostream. This is a
|
||||
/// simple adaptor class.
|
||||
class raw_os_ostream : public raw_ostream {
|
||||
|
@ -12,6 +12,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Config/config.h"
|
||||
#include <ostream>
|
||||
|
||||
@ -134,6 +135,55 @@ raw_ostream &raw_ostream::write(const char *Ptr, unsigned Size) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Formatted output.
|
||||
raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) {
|
||||
// If we have more than a few bytes left in our output buffer, try formatting
|
||||
// directly onto its end.
|
||||
unsigned NextBufferSize = 127;
|
||||
if (OutBufEnd-OutBufCur > 3) {
|
||||
unsigned BufferBytesLeft = OutBufEnd-OutBufCur;
|
||||
unsigned BytesUsed = Fmt.print(OutBufCur, BufferBytesLeft);
|
||||
|
||||
// Common case is that we have plenty of space.
|
||||
if (BytesUsed < BufferBytesLeft) {
|
||||
OutBufCur += BytesUsed;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Otherwise, we overflowed and the return value tells us the size to try
|
||||
// again with.
|
||||
NextBufferSize = BytesUsed;
|
||||
}
|
||||
|
||||
// If we got here, we didn't have enough space in the output buffer for the
|
||||
// string. Try printing into a SmallVector that is resized to have enough
|
||||
// space. Iterate until we win.
|
||||
SmallVector<char, 128> V;
|
||||
|
||||
while (1) {
|
||||
V.resize(NextBufferSize);
|
||||
|
||||
// Try formatting into the SmallVector.
|
||||
unsigned BytesUsed = Fmt.print(&V[0], NextBufferSize);
|
||||
|
||||
// If BytesUsed fit into the vector, we win.
|
||||
if (BytesUsed < NextBufferSize)
|
||||
return write(&V[0], BytesUsed);
|
||||
|
||||
// Otherwise, try again with a new size.
|
||||
assert(BytesUsed > NextBufferSize && "Didn't grow buffer!?");
|
||||
NextBufferSize = BytesUsed;
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Formatted Output
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Out of line virtual method.
|
||||
void format_object_base::home() {
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// raw_fd_ostream
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
Loading…
x
Reference in New Issue
Block a user