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