1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef _INFOSINK_INCLUDED_ 16 #define _INFOSINK_INCLUDED_ 17 18 #include <math.h> 19 #include "Common.h" 20 21 // Returns the fractional part of the given floating-point number. 22 inline float fractionalPart(float f) { 23 float intPart = 0.0f; 24 return modff(f, &intPart); 25 } 26 27 // 28 // TPrefixType is used to centralize how info log messages start. 29 // See below. 30 // 31 enum TPrefixType { 32 EPrefixNone, 33 EPrefixWarning, 34 EPrefixError, 35 EPrefixInternalError, 36 EPrefixUnimplemented, 37 EPrefixNote 38 }; 39 40 // 41 // Encapsulate info logs for all objects that have them. 42 // 43 // The methods are a general set of tools for getting a variety of 44 // messages and types inserted into the log. 45 // 46 class TInfoSinkBase { 47 public: 48 TInfoSinkBase() {} 49 50 template <typename T> 51 TInfoSinkBase& operator<<(const T& t) { 52 TPersistStringStream stream; 53 stream << t; 54 sink.append(stream.str()); 55 return *this; 56 } 57 // Override << operator for specific types. It is faster to append strings 58 // and characters directly to the sink. 59 TInfoSinkBase& operator<<(char c) { 60 sink.append(1, c); 61 return *this; 62 } 63 TInfoSinkBase& operator<<(const char* str) { 64 sink.append(str); 65 return *this; 66 } 67 TInfoSinkBase& operator<<(const TPersistString& str) { 68 sink.append(str); 69 return *this; 70 } 71 TInfoSinkBase& operator<<(const TString& str) { 72 sink.append(str.c_str()); 73 return *this; 74 } 75 // Make sure floats are written with correct precision. 76 TInfoSinkBase& operator<<(float f) { 77 // Make sure that at least one decimal point is written. If a number 78 // does not have a fractional part, the default precision format does 79 // not write the decimal portion which gets interpreted as integer by 80 // the compiler. 81 TPersistStringStream stream; 82 if (fractionalPart(f) == 0.0f) { 83 stream.precision(1); 84 stream << std::showpoint << std::fixed << f; 85 } else { 86 stream.unsetf(std::ios::fixed); 87 stream.unsetf(std::ios::scientific); 88 stream.precision(8); 89 stream << f; 90 } 91 sink.append(stream.str()); 92 return *this; 93 } 94 // Write boolean values as their names instead of integral value. 95 TInfoSinkBase& operator<<(bool b) { 96 const char* str = b ? "true" : "false"; 97 sink.append(str); 98 return *this; 99 } 100 101 void erase() { sink.clear(); } 102 int size() { return static_cast<int>(sink.size()); } 103 104 const TPersistString& str() const { return sink; } 105 const char* c_str() const { return sink.c_str(); } 106 107 void prefix(TPrefixType message); 108 void location(const TSourceLoc& loc); 109 void message(TPrefixType message, const char* s); 110 void message(TPrefixType message, const char* s, TSourceLoc loc); 111 112 private: 113 TPersistString sink; 114 }; 115 116 class TInfoSink { 117 public: 118 TInfoSinkBase info; 119 TInfoSinkBase debug; 120 TInfoSinkBase obj; 121 }; 122 123 #endif // _INFOSINK_INCLUDED_ 124