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