summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Support/raw_ostream.h71
-rw-r--r--lib/Support/raw_ostream.cpp50
2 files changed, 116 insertions, 5 deletions
diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h
index 34e40da517..58d5be2741 100644
--- a/include/llvm/Support/raw_ostream.h
+++ b/include/llvm/Support/raw_ostream.h
@@ -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 {
diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp
index d776fa583f..104dc77149 100644
--- a/lib/Support/raw_ostream.cpp
+++ b/lib/Support/raw_ostream.cpp
@@ -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
//===----------------------------------------------------------------------===//