1/*
2 * Copyright (C) 2009, 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#ifndef StringBuilder_h
27#define StringBuilder_h
28
29#include <wtf/Vector.h>
30#include <wtf/text/WTFString.h>
31
32namespace WTF {
33
34class StringBuilder {
35public:
36    StringBuilder()
37        : m_length(0)
38    {
39    }
40
41    void append(const UChar*, unsigned);
42    void append(const char*, unsigned);
43
44    void append(const String& string)
45    {
46        // If we're appending to an empty string, and there is not buffer
47        // (in case reserveCapacity has been called) then just retain the
48        // string.
49        if (!m_length && !m_buffer) {
50            m_string = string;
51            m_length = string.length();
52            return;
53        }
54        append(string.characters(), string.length());
55    }
56
57    void append(const char* characters)
58    {
59        if (characters)
60            append(characters, strlen(characters));
61    }
62
63    void append(UChar c)
64    {
65        if (m_buffer && m_length < m_buffer->length() && m_string.isNull())
66            m_bufferCharacters[m_length++] = c;
67        else
68            append(&c, 1);
69    }
70
71    void append(char c)
72    {
73        if (m_buffer && m_length < m_buffer->length() && m_string.isNull())
74            m_bufferCharacters[m_length++] = (unsigned char)c;
75        else
76            append(&c, 1);
77    }
78
79    String toString()
80    {
81        if (m_string.isNull()) {
82            shrinkToFit();
83            reifyString();
84        }
85        return m_string;
86    }
87
88    String toStringPreserveCapacity()
89    {
90        if (m_string.isNull())
91            reifyString();
92        return m_string;
93    }
94
95    unsigned length() const
96    {
97        return m_length;
98    }
99
100    bool isEmpty() const { return !length(); }
101
102    void reserveCapacity(unsigned newCapacity);
103
104    void resize(unsigned newSize);
105
106    void shrinkToFit();
107
108    UChar operator[](unsigned i) const
109    {
110        ASSERT(i < m_length);
111        if (!m_string.isNull())
112            return m_string[i];
113        ASSERT(m_buffer);
114        return m_buffer->characters()[i];
115    }
116
117    void clear()
118    {
119        m_length = 0;
120        m_string = String();
121        m_buffer = 0;
122    }
123
124private:
125    void allocateBuffer(const UChar* currentCharacters, unsigned requiredLength);
126    UChar* appendUninitialized(unsigned length);
127    void reifyString();
128
129    unsigned m_length;
130    String m_string;
131    RefPtr<StringImpl> m_buffer;
132    UChar* m_bufferCharacters;
133};
134
135} // namespace WTF
136
137using WTF::StringBuilder;
138
139#endif // StringBuilder_h
140