Refactored InfoSink. I have replaced most instances of sprintf with std::ostringstream to make it safer. I have made sure that everything still compiles and passes conformance tests.
Review URL: http://codereview.appspot.com/1391041
git-svn-id: https://angleproject.googlecode.com/svn/trunk@322 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/InfoSink.h b/src/compiler/InfoSink.h
index 6ddf6b0..5c25c03 100644
--- a/src/compiler/InfoSink.h
+++ b/src/compiler/InfoSink.h
@@ -8,7 +8,6 @@
#define _INFOSINK_INCLUDED_
#include <math.h>
-
#include "compiler/Common.h"
// Returns the fractional part of the given floating-point number.
@@ -30,11 +29,6 @@
EPrefixNote
};
-enum TOutputStream {
- ENull = 0,
- EStdOut = 0x01,
- EString = 0x02,
-};
//
// Encapsulate info logs for all objects that have them.
//
@@ -43,72 +37,68 @@
//
class TInfoSinkBase {
public:
- TInfoSinkBase() : outputStream(EString) {}
- void erase() { sink.erase(); }
- TInfoSinkBase& operator<<(const TPersistString& t) { append(t); return *this; }
- TInfoSinkBase& operator<<(char c) { append(1, c); return *this; }
- TInfoSinkBase& operator<<(const char* s) { append(s); return *this; }
- TInfoSinkBase& operator<<(int n) { append(String(n)); return *this; }
- TInfoSinkBase& operator<<(const unsigned int n) { append(String(n)); return *this; }
- TInfoSinkBase& operator<<(float n) {
- char buf[40];
- // Make sure that at least one decimal point is written. If a number
- // does not have a fractional part, %g does not written the decimal
- // portion which gets interpreted as integer by the compiler.
- const char* format = fractionalPart(n) == 0.0f ? "%.1f" : "%.8g";
- sprintf(buf, format, n);
- append(buf);
+ TInfoSinkBase() {}
+
+ template <typename T>
+ TInfoSinkBase& operator<<(const T& t) {
+ TPersistStringStream stream;
+ stream << t;
+ sink.append(stream.str());
return *this;
}
- TInfoSinkBase& operator+(const TPersistString& t) { append(t); return *this; }
- TInfoSinkBase& operator+(const TString& t) { append(t); return *this; }
- TInfoSinkBase& operator<<(const TString& t) { append(t); return *this; }
- TInfoSinkBase& operator+(const char* s) { append(s); return *this; }
- const char* c_str() const { return sink.c_str(); }
- void prefix(TPrefixType message) {
- switch(message) {
- case EPrefixNone: break;
- case EPrefixWarning: append("WARNING: "); break;
- case EPrefixError: append("ERROR: "); break;
- case EPrefixInternalError: append("INTERNAL ERROR: "); break;
- case EPrefixUnimplemented: append("UNIMPLEMENTED: "); break;
- case EPrefixNote: append("NOTE: "); break;
- default: append("UNKOWN ERROR: "); break;
+ // Override << operator for specific types. It is faster to append strings
+ // and characters directly to the sink.
+ TInfoSinkBase& operator<<(char c) {
+ sink.append(1, c);
+ return *this;
+ }
+ TInfoSinkBase& operator<<(const char* str) {
+ sink.append(str);
+ return *this;
+ }
+ TInfoSinkBase& operator<<(const TPersistString& str) {
+ sink.append(str);
+ return *this;
+ }
+ TInfoSinkBase& operator<<(const TString& str) {
+ sink.append(str.c_str());
+ return *this;
+ }
+ // Make sure floats are written with correct precision.
+ TInfoSinkBase& operator<<(float f) {
+ // Make sure that at least one decimal point is written. If a number
+ // does not have a fractional part, the default precision format does
+ // not write the decimal portion which gets interpreted as integer by
+ // the compiler.
+ TPersistStringStream stream;
+ if (fractionalPart(f) == 0.0f) {
+ stream.precision(2);
+ stream << std::showpoint << f;
+ } else {
+ stream << f;
}
+ sink.append(stream.str());
+ return *this;
}
- void location(TSourceLoc loc) {
- append(FormatSourceLoc(loc).c_str());
- append(": ");
- }
- void message(TPrefixType message, const char* s) {
- prefix(message);
- append(s);
- append("\n");
- }
- void message(TPrefixType message, const char* s, TSourceLoc loc) {
- prefix(message);
- location(loc);
- append(s);
- append("\n");
- }
-
- void setOutputStream(int output = 4)
- {
- outputStream = output;
+ // Write boolean values as their names instead of integral value.
+ TInfoSinkBase& operator<<(bool b) {
+ const char* str = b ? "true" : "false";
+ sink.append(str);
+ return *this;
}
-protected:
- void append(const char *s);
+ void erase() { sink.clear(); }
- void append(int count, char c);
- void append(const TPersistString& t);
- void append(const TString& t);
+ const TPersistString& str() const { return sink; }
+ const char* c_str() const { return sink.c_str(); }
- void checkMem(size_t growth) { if (sink.capacity() < sink.size() + growth + 2)
- sink.reserve(sink.capacity() + sink.capacity() / 2); }
- void appendToStream(const char* s);
+ void prefix(TPrefixType message);
+ void location(TSourceLoc loc);
+ void message(TPrefixType message, const char* s);
+ void message(TPrefixType message, const char* s, TSourceLoc loc);
+
+private:
TPersistString sink;
- int outputStream;
};
class TInfoSink {