michael@0: // michael@0: // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: // michael@0: michael@0: #ifndef _INFOSINK_INCLUDED_ michael@0: #define _INFOSINK_INCLUDED_ michael@0: michael@0: #include michael@0: #include "compiler/Common.h" michael@0: michael@0: // Returns the fractional part of the given floating-point number. michael@0: inline float fractionalPart(float f) { michael@0: float intPart = 0.0f; michael@0: return modff(f, &intPart); michael@0: } michael@0: michael@0: // michael@0: // TPrefixType is used to centralize how info log messages start. michael@0: // See below. michael@0: // michael@0: enum TPrefixType { michael@0: EPrefixNone, michael@0: EPrefixWarning, michael@0: EPrefixError, michael@0: EPrefixInternalError, michael@0: EPrefixUnimplemented, michael@0: EPrefixNote michael@0: }; michael@0: michael@0: // michael@0: // Encapsulate info logs for all objects that have them. michael@0: // michael@0: // The methods are a general set of tools for getting a variety of michael@0: // messages and types inserted into the log. michael@0: // michael@0: class TInfoSinkBase { michael@0: public: michael@0: TInfoSinkBase() {} michael@0: michael@0: template michael@0: TInfoSinkBase& operator<<(const T& t) { michael@0: TPersistStringStream stream; michael@0: stream << t; michael@0: sink.append(stream.str()); michael@0: return *this; michael@0: } michael@0: // Override << operator for specific types. It is faster to append strings michael@0: // and characters directly to the sink. michael@0: TInfoSinkBase& operator<<(char c) { michael@0: sink.append(1, c); michael@0: return *this; michael@0: } michael@0: TInfoSinkBase& operator<<(const char* str) { michael@0: sink.append(str); michael@0: return *this; michael@0: } michael@0: TInfoSinkBase& operator<<(const TPersistString& str) { michael@0: sink.append(str); michael@0: return *this; michael@0: } michael@0: TInfoSinkBase& operator<<(const TString& str) { michael@0: sink.append(str.c_str()); michael@0: return *this; michael@0: } michael@0: // Make sure floats are written with correct precision. michael@0: TInfoSinkBase& operator<<(float f) { michael@0: // Make sure that at least one decimal point is written. If a number michael@0: // does not have a fractional part, the default precision format does michael@0: // not write the decimal portion which gets interpreted as integer by michael@0: // the compiler. michael@0: TPersistStringStream stream; michael@0: if (fractionalPart(f) == 0.0f) { michael@0: stream.precision(1); michael@0: stream << std::showpoint << std::fixed << f; michael@0: } else { michael@0: stream.unsetf(std::ios::fixed); michael@0: stream.unsetf(std::ios::scientific); michael@0: stream.precision(8); michael@0: stream << f; michael@0: } michael@0: sink.append(stream.str()); michael@0: return *this; michael@0: } michael@0: // Write boolean values as their names instead of integral value. michael@0: TInfoSinkBase& operator<<(bool b) { michael@0: const char* str = b ? "true" : "false"; michael@0: sink.append(str); michael@0: return *this; michael@0: } michael@0: michael@0: void erase() { sink.clear(); } michael@0: int size() { return static_cast(sink.size()); } michael@0: michael@0: const TPersistString& str() const { return sink; } michael@0: const char* c_str() const { return sink.c_str(); } michael@0: michael@0: void prefix(TPrefixType p); michael@0: void location(int file, int line); michael@0: void location(const TSourceLoc& loc); michael@0: void message(TPrefixType p, const TSourceLoc& loc, const char* m); michael@0: michael@0: private: michael@0: TPersistString sink; michael@0: }; michael@0: michael@0: class TInfoSink { michael@0: public: michael@0: TInfoSinkBase info; michael@0: TInfoSinkBase debug; michael@0: TInfoSinkBase obj; michael@0: }; michael@0: michael@0: #endif // _INFOSINK_INCLUDED_