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