Reviewed by Mitz.
[WebKit-https.git] / WebCore / platform / SegmentedString.cpp
1 /*
2     Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
3
4     This library is free software; you can redistribute it and/or
5     modify it under the terms of the GNU Library General Public
6     License as published by the Free Software Foundation; either
7     version 2 of the License, or (at your option) any later version.
8
9     This library is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12     Library General Public License for more details.
13
14     You should have received a copy of the GNU Library General Public License
15     along with this library; see the file COPYING.LIB.  If not, write to
16     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17     Boston, MA 02110-1301, USA.
18 */
19
20 #include "config.h"
21 #include "SegmentedString.h"
22
23 namespace WebCore {
24
25 SegmentedString::SegmentedString(const SegmentedString &other) :
26     m_pushedChar1(other.m_pushedChar1), m_pushedChar2(other.m_pushedChar2), m_currentString(other.m_currentString),
27     m_substrings(other.m_substrings), m_composite(other.m_composite)
28 {
29     if (other.m_currentChar == &other.m_pushedChar1)
30         m_currentChar = &m_pushedChar1;
31     else if (other.m_currentChar == &other.m_pushedChar2)
32         m_currentChar = &m_pushedChar2;
33     else
34         m_currentChar = other.m_currentChar;
35 }
36
37 const SegmentedString& SegmentedString::operator=(const SegmentedString &other)
38 {
39     m_pushedChar1 = other.m_pushedChar1;
40     m_pushedChar2 = other.m_pushedChar2;
41     m_currentString = other.m_currentString;
42     m_substrings = other.m_substrings;
43     m_composite = other.m_composite;
44     if (other.m_currentChar == &other.m_pushedChar1)
45         m_currentChar = &m_pushedChar1;
46     else if (other.m_currentChar == &other.m_pushedChar2)
47         m_currentChar = &m_pushedChar2;
48     else
49         m_currentChar = other.m_currentChar;
50     return *this;
51 }
52
53 unsigned SegmentedString::length() const
54 {
55     unsigned length = m_currentString.m_length;
56     if (m_pushedChar1) {
57         ++length;
58         if (m_pushedChar2)
59             ++length;
60     }
61     if (m_composite) {
62         DeprecatedValueListConstIterator<SegmentedSubstring> i = m_substrings.begin();
63         DeprecatedValueListConstIterator<SegmentedSubstring> e = m_substrings.end();
64         for (; i != e; ++i)
65             length += (*i).m_length;
66     }
67     return length;
68 }
69
70 void SegmentedString::setExcludeLineNumbers()
71 {
72     if (m_composite) {
73         DeprecatedValueListIterator<SegmentedSubstring> i = m_substrings.begin();
74         DeprecatedValueListIterator<SegmentedSubstring> e = m_substrings.end();
75         for (; i != e; ++i)
76             (*i).setExcludeLineNumbers();
77     } else
78         m_currentString.setExcludeLineNumbers();
79 }
80
81 void SegmentedString::clear()
82 {
83     m_pushedChar1 = 0;
84     m_pushedChar2 = 0;
85     m_currentChar = 0;
86     m_currentString.clear();
87     m_substrings.clear();
88     m_composite = false;
89 }
90
91 void SegmentedString::append(const SegmentedSubstring &s)
92 {
93     if (s.m_length) {
94         if (!m_currentString.m_length) {
95             m_currentString = s;
96         } else {
97             m_substrings.append(s);
98             m_composite = true;
99         }
100     }
101 }
102
103 void SegmentedString::prepend(const SegmentedSubstring &s)
104 {
105     ASSERT(!escaped());
106     if (s.m_length) {
107         if (!m_currentString.m_length)
108             m_currentString = s;
109         else {
110             // Shift our m_currentString into our list.
111             m_substrings.prepend(m_currentString);
112             m_currentString = s;
113             m_composite = true;
114         }
115     }
116 }
117
118 void SegmentedString::append(const SegmentedString &s)
119 {
120     ASSERT(!s.escaped());
121     append(s.m_currentString);
122     if (s.m_composite) {
123         DeprecatedValueListConstIterator<SegmentedSubstring> i = s.m_substrings.begin();
124         DeprecatedValueListConstIterator<SegmentedSubstring> e = s.m_substrings.end();
125         for (; i != e; ++i)
126             append(*i);
127     }
128     m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current;
129 }
130
131 void SegmentedString::prepend(const SegmentedString &s)
132 {
133     ASSERT(!escaped());
134     ASSERT(!s.escaped());
135     if (s.m_composite) {
136         DeprecatedValueListConstIterator<SegmentedSubstring> i = s.m_substrings.fromLast();
137         DeprecatedValueListConstIterator<SegmentedSubstring> e = s.m_substrings.end();
138         for (; i != e; --i)
139             prepend(*i);
140     }
141     prepend(s.m_currentString);
142     m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current;
143 }
144
145 void SegmentedString::advanceSubstring()
146 {
147     if (m_composite) {
148         m_currentString = m_substrings.first();
149         m_substrings.remove(m_substrings.begin());
150         if (m_substrings.isEmpty())
151             m_composite = false;
152     } else {
153         m_currentString.clear();
154     }
155 }
156
157 String SegmentedString::toString() const
158 {
159     String result;
160     if (m_pushedChar1) {
161         result.append(m_pushedChar1);
162         if (m_pushedChar2)
163             result.append(m_pushedChar2);
164     }
165     m_currentString.appendTo(result);
166     if (m_composite) {
167         DeprecatedValueListConstIterator<SegmentedSubstring> i = m_substrings.begin();
168         DeprecatedValueListConstIterator<SegmentedSubstring> e = m_substrings.end();
169         for (; i != e; ++i)
170             (*i).appendTo(result);
171     }
172     return result;
173 }
174
175 void SegmentedString::advanceSlowCase()
176 {
177     if (m_pushedChar1) {
178         m_pushedChar1 = m_pushedChar2;
179         m_pushedChar2 = 0;
180     } else if (m_currentString.m_current) {
181         ++m_currentString.m_current;
182         if (--m_currentString.m_length == 0)
183             advanceSubstring();
184     }
185     m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current;
186 }
187
188 void SegmentedString::advanceSlowCase(int& lineNumber)
189 {
190     if (m_pushedChar1) {
191         m_pushedChar1 = m_pushedChar2;
192         m_pushedChar2 = 0;
193     } else if (m_currentString.m_current) {
194         if (*m_currentString.m_current++ == '\n' && !m_currentString.excludeLineNumbers())
195             ++lineNumber;
196         if (--m_currentString.m_length == 0)
197             advanceSubstring();
198     }
199     m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current;
200 }
201
202 }