1 // 2 // Copyright 2002 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 #ifndef COMPILER_TRANSLATOR_INFOSINK_H_ 8 #define COMPILER_TRANSLATOR_INFOSINK_H_ 9 10 #include <math.h> 11 #include <stdlib.h> 12 #include "GLSLANG/ShaderLang.h" 13 #include "compiler/translator/Common.h" 14 #include "compiler/translator/Severity.h" 15 16 namespace sh 17 { 18 19 class ImmutableString; 20 class TSymbol; 21 class TType; 22 23 // Returns the fractional part of the given floating-point number. fractionalPart(float f)24inline float fractionalPart(float f) 25 { 26 float intPart = 0.0f; 27 return modff(f, &intPart); 28 } 29 30 class ImmutableString; 31 32 // 33 // Encapsulate info logs for all objects that have them. 34 // 35 // The methods are a general set of tools for getting a variety of 36 // messages and types inserted into the log. 37 // 38 class TInfoSinkBase 39 { 40 public: TInfoSinkBase()41 TInfoSinkBase() {} 42 43 template <typename T> 44 TInfoSinkBase &operator<<(const T &t) 45 { 46 TPersistStringStream stream = sh::InitializeStream<TPersistStringStream>(); 47 stream << t; 48 sink.append(stream.str()); 49 return *this; 50 } 51 // Override << operator for specific types. It is faster to append strings 52 // and characters directly to the sink. 53 TInfoSinkBase &operator<<(char c) 54 { 55 sink.append(1, c); 56 return *this; 57 } 58 TInfoSinkBase &operator<<(const char *str) 59 { 60 sink.append(str); 61 return *this; 62 } 63 TInfoSinkBase &operator<<(const TPersistString &str) 64 { 65 sink.append(str); 66 return *this; 67 } 68 TInfoSinkBase &operator<<(const TString &str) 69 { 70 sink.append(str.c_str()); 71 return *this; 72 } 73 TInfoSinkBase &operator<<(const ImmutableString &str); 74 75 TInfoSinkBase &operator<<(const TType &type); 76 TInfoSinkBase &operator<<(const TSymbol &symbol); 77 78 // Make sure floats are written with correct precision. 79 TInfoSinkBase &operator<<(float f) 80 { 81 // Make sure that at least one decimal point is written. If a number 82 // does not have a fractional part, the default precision format does 83 // not write the decimal portion which gets interpreted as integer by 84 // the compiler. 85 TPersistStringStream stream = sh::InitializeStream<TPersistStringStream>(); 86 if (fractionalPart(f) == 0.0f) 87 { 88 stream.precision(1); 89 stream << std::showpoint << std::fixed << f; 90 } 91 else 92 { 93 stream.unsetf(std::ios::fixed); 94 stream.unsetf(std::ios::scientific); 95 stream.precision(9); 96 stream << f; 97 } 98 sink.append(stream.str()); 99 return *this; 100 } 101 // Write boolean values as their names instead of integral value. 102 TInfoSinkBase &operator<<(bool b) 103 { 104 const char *str = b ? "true" : "false"; 105 sink.append(str); 106 return *this; 107 } 108 erase()109 void erase() 110 { 111 sink.clear(); 112 binarySink.clear(); 113 } size()114 int size() { return static_cast<int>(isBinary() ? binarySink.size() : sink.size()); } 115 str()116 const TPersistString &str() const 117 { 118 ASSERT(!isBinary()); 119 return sink; 120 } c_str()121 const char *c_str() const 122 { 123 ASSERT(!isBinary()); 124 return sink.c_str(); 125 } 126 127 void prefix(Severity severity); 128 void location(int file, int line); 129 isBinary()130 bool isBinary() const { return !binarySink.empty(); } setBinary(BinaryBlob && binary)131 void setBinary(BinaryBlob &&binary) { binarySink = std::move(binary); } getBinary()132 const BinaryBlob &getBinary() const 133 { 134 ASSERT(isBinary()); 135 return binarySink; 136 } 137 138 private: 139 // The data in the info sink is either in human readable form (|sink|) or binary (|binarySink|). 140 TPersistString sink; 141 BinaryBlob binarySink; 142 }; 143 144 class TInfoSink 145 { 146 public: 147 TInfoSinkBase info; 148 TInfoSinkBase debug; 149 TInfoSinkBase obj; 150 }; 151 152 } // namespace sh 153 154 #endif // COMPILER_TRANSLATOR_INFOSINK_H_ 155