1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Copyright 2005, Google Inc.
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// All rights reserved.
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Redistribution and use in source and binary forms, with or without
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// modification, are permitted provided that the following conditions are
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// met:
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//     * Redistributions of source code must retain the above copyright
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// notice, this list of conditions and the following disclaimer.
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//     * Redistributions in binary form must reproduce the above
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// copyright notice, this list of conditions and the following disclaimer
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// in the documentation and/or other materials provided with the
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// distribution.
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//     * Neither the name of Google Inc. nor the names of its
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// contributors may be used to endorse or promote products derived from
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// this software without specific prior written permission.
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Author: wan@google.com (Zhanyong Wan)
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// The Google C++ Testing Framework (Google Test)
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// This header file defines the Message class.
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// leave some internal implementation details in this header file.
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// They are clearly marked by comments like this:
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//   // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Such code is NOT meant to be used by a user directly, and is subject
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// to CHANGE WITHOUT NOTICE.  Therefore DO NOT DEPEND ON IT in a user
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// program!
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <limits>
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "gtest/internal/gtest-string.h"
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "gtest/internal/gtest-internal.h"
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnamespace testing {
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// The Message class works like an ostream repeater.
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Typical usage:
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//   1. You stream a bunch of values to a Message object.
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//      It will remember the text in a stringstream.
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//   2. Then you stream the Message object to an ostream.
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//      This causes the text in the Message to be streamed
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//      to the ostream.
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// For example;
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//   testing::Message foo;
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//   foo << 1 << " != " << 2;
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//   std::cout << foo;
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// will print "1 != 2".
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Message is not intended to be inherited from.  In particular, its
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// destructor is not virtual.
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Note that stringstream behaves differently in gcc and in MSVC.  You
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// can stream a NULL char pointer to it in the former, but not in the
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// latter (it causes an access violation if you do).  The Message
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// class hides this difference by treating a NULL char pointer as
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// "(null)".
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass GTEST_API_ Message {
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org private:
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // The type of basic IO manipulators (endl, ends, and flush) for
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // narrow streams.
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&);
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org public:
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Constructs an empty Message.
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // We allocate the stringstream separately because otherwise each use of
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // stack frame leading to huge stack frames in some cases; gcc does not reuse
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // the stack space.
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  Message() : ss_(new ::std::stringstream) {
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    // By default, we want there to be enough precision when printing
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    // a double to a Message.
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2);
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Copy constructor.
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  Message(const Message& msg) : ss_(new ::std::stringstream) {  // NOLINT
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *ss_ << msg.GetString();
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Constructs a Message from a C-string.
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  explicit Message(const char* str) : ss_(new ::std::stringstream) {
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *ss_ << str;
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if GTEST_OS_SYMBIAN
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Streams a value (either a pointer or not) to this object.
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  template <typename T>
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  inline Message& operator <<(const T& value) {
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    StreamHelper(typename internal::is_pointer<T>::type(), value);
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return *this;
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Streams a non-pointer value to this object.
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  template <typename T>
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  inline Message& operator <<(const T& val) {
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    ::GTestStreamToHelper(ss_.get(), val);
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return *this;
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Streams a pointer value to this object.
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  //
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // This function is an overload of the previous one.  When you
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // stream a pointer to a Message, this definition will be used as it
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // is more specialized.  (The C++ Standard, section
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // [temp.func.order].)  If you stream a non-pointer, then the
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // previous definition will be used.
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  //
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // The reason for this overload is that streaming a NULL pointer to
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // ostream is undefined behavior.  Depending on the compiler, you
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // may get "0", "(nil)", "(null)", or an access violation.  To
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // ensure consistent result across compilers, we always treat NULL
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // as "(null)".
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  template <typename T>
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  inline Message& operator <<(T* const& pointer) {  // NOLINT
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (pointer == NULL) {
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *ss_ << "(null)";
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    } else {
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ::GTestStreamToHelper(ss_.get(), pointer);
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return *this;
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif  // GTEST_OS_SYMBIAN
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Since the basic IO manipulators are overloaded for both narrow
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // and wide streams, we have to provide this specialized definition
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // of operator <<, even though its body is the same as the
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // templatized version above.  Without this definition, streaming
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // endl or other basic IO manipulators to Message will confuse the
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // compiler.
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  Message& operator <<(BasicNarrowIoManip val) {
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *ss_ << val;
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return *this;
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Instead of 1/0, we want to see true/false for bool values.
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  Message& operator <<(bool b) {
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return *this << (b ? "true" : "false");
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // These two overloads allow streaming a wide C string to a Message
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // using the UTF-8 encoding.
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  Message& operator <<(const wchar_t* wide_c_str) {
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return *this << internal::String::ShowWideCString(wide_c_str);
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  Message& operator <<(wchar_t* wide_c_str) {
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return *this << internal::String::ShowWideCString(wide_c_str);
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if GTEST_HAS_STD_WSTRING
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Converts the given wide string to a narrow string using the UTF-8
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // encoding, and streams the result to this Message object.
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  Message& operator <<(const ::std::wstring& wstr);
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif  // GTEST_HAS_STD_WSTRING
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if GTEST_HAS_GLOBAL_WSTRING
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Converts the given wide string to a narrow string using the UTF-8
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // encoding, and streams the result to this Message object.
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  Message& operator <<(const ::wstring& wstr);
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif  // GTEST_HAS_GLOBAL_WSTRING
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Gets the text streamed to this object so far as a String.
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Each '\0' character in the buffer is replaced with "\\0".
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  //
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  internal::String GetString() const {
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return internal::StringStreamToString(ss_.get());
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org private:
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if GTEST_OS_SYMBIAN
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // These are needed as the Nokia Symbian Compiler cannot decide between
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // const T& and const T* in a function template. The Nokia compiler _can_
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // decide between class template specializations for T and T*, so a
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // tr1::type_traits-like is_pointer works, and we can overload on that.
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  template <typename T>
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  inline void StreamHelper(internal::true_type /*dummy*/, T* pointer) {
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (pointer == NULL) {
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *ss_ << "(null)";
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    } else {
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ::GTestStreamToHelper(ss_.get(), pointer);
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  template <typename T>
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  inline void StreamHelper(internal::false_type /*dummy*/, const T& value) {
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    ::GTestStreamToHelper(ss_.get(), value);
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif  // GTEST_OS_SYMBIAN
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // We'll hold the text streamed to this object here.
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  const internal::scoped_ptr< ::std::stringstream> ss_;
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // We declare (but don't implement) this to prevent the compiler
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // from implementing the assignment operator.
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void operator=(const Message&);
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Streams a Message to an ostream.
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orginline std::ostream& operator <<(std::ostream& os, const Message& sb) {
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return os << sb.GetString();
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}  // namespace testing
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif  // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
231