1/*
2 * Copyright (C) 2004, 2008, 2010 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "TextStream.h"
28
29#include "FloatPoint.h"
30#include "FloatRect.h"
31#include "IntPoint.h"
32#include "IntRect.h"
33#include "LayoutRect.h"
34#include "LayoutUnit.h"
35#include <wtf/MathExtras.h>
36#include <wtf/StringExtras.h>
37#include <wtf/text/WTFString.h>
38
39namespace WebCore {
40
41static const size_t printBufferSize = 100; // large enough for any integer or floating point value in string format, including trailing null character
42
43static inline bool hasFractions(double val)
44{
45    static const double s_epsilon = 0.0001;
46    int ival = static_cast<int>(val);
47    double dval = static_cast<double>(ival);
48    return fabs(val - dval) > s_epsilon;
49}
50
51TextStream& TextStream::operator<<(bool b)
52{
53    return *this << (b ? "1" : "0");
54}
55
56TextStream& TextStream::operator<<(int i)
57{
58    m_text.appendNumber(i);
59    return *this;
60}
61
62TextStream& TextStream::operator<<(unsigned i)
63{
64    m_text.appendNumber(i);
65    return *this;
66}
67
68TextStream& TextStream::operator<<(long i)
69{
70    m_text.appendNumber(i);
71    return *this;
72}
73
74TextStream& TextStream::operator<<(unsigned long i)
75{
76    m_text.appendNumber(i);
77    return *this;
78}
79
80TextStream& TextStream::operator<<(long long i)
81{
82    m_text.appendNumber(i);
83    return *this;
84}
85
86TextStream& TextStream::operator<<(unsigned long long i)
87{
88    m_text.appendNumber(i);
89    return *this;
90}
91
92TextStream& TextStream::operator<<(float f)
93{
94    m_text.append(String::numberToStringFixedWidth(f, 2));
95    return *this;
96}
97
98TextStream& TextStream::operator<<(double d)
99{
100    m_text.append(String::numberToStringFixedWidth(d, 2));
101    return *this;
102}
103
104TextStream& TextStream::operator<<(const char* string)
105{
106    m_text.append(string);
107    return *this;
108}
109
110TextStream& TextStream::operator<<(const void* p)
111{
112    char buffer[printBufferSize];
113    snprintf(buffer, sizeof(buffer) - 1, "%p", p);
114    return *this << buffer;
115}
116
117TextStream& TextStream::operator<<(const String& string)
118{
119    m_text.append(string);
120    return *this;
121}
122
123TextStream& TextStream::operator<<(const FormatNumberRespectingIntegers& numberToFormat)
124{
125    if (hasFractions(numberToFormat.value))
126        return *this << numberToFormat.value;
127
128    m_text.appendNumber(static_cast<int>(numberToFormat.value));
129    return *this;
130}
131
132TextStream& TextStream::operator<<(const IntPoint& p)
133{
134    return *this << "(" << p.x() << "," << p.y() << ")";
135}
136
137TextStream& TextStream::operator<<(const IntRect& r)
138{
139    return *this  << "at (" << r.x() << "," << r.y() << ") size " << r.width() << "x" << r.height();
140}
141
142TextStream& TextStream::operator<<(const FloatPoint& p)
143{
144    return *this << "(" << TextStream::FormatNumberRespectingIntegers(p.x())
145        << "," << TextStream::FormatNumberRespectingIntegers(p.y()) << ")";
146}
147
148TextStream& TextStream::operator<<(const FloatSize& s)
149{
150    return *this << "width=" << TextStream::FormatNumberRespectingIntegers(s.width())
151        << " height=" << TextStream::FormatNumberRespectingIntegers(s.height());
152}
153
154TextStream& TextStream::operator<<(const LayoutUnit& v)
155{
156    return *this << TextStream::FormatNumberRespectingIntegers(v.toFloat());
157}
158
159TextStream& TextStream::operator<<(const LayoutPoint& p)
160{
161    // FIXME: These should be printed as floats. Keeping them ints for consistency with pervious test expectations.
162    return *this << "(" << p.x().toInt() << "," << p.y().toInt() << ")";
163}
164
165TextStream& TextStream::operator<<(const LayoutRect& r)
166{
167    // FIXME: These should be printed as floats. Keeping them ints for consistency with previous test expectations.
168    return *this << pixelSnappedIntRect(r);
169}
170
171String TextStream::release()
172{
173    String result = m_text.toString();
174    m_text.clear();
175    return result;
176}
177
178void writeIndent(TextStream& ts, int indent)
179{
180    for (int i = 0; i != indent; ++i)
181        ts << "  ";
182}
183
184}
185