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