Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / text / SegmentedString.cpp
1 /*
2     Copyright (C) 2004, 2005, 2006, 2007, 2008 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 "platform/text/SegmentedString.h"
22
23 namespace blink {
24
25 unsigned SegmentedString::length() const
26 {
27     unsigned length = m_currentString.m_length;
28     if (m_pushedChar1) {
29         ++length;
30         if (m_pushedChar2)
31             ++length;
32     }
33     if (isComposite()) {
34         Deque<SegmentedSubstring>::const_iterator it = m_substrings.begin();
35         Deque<SegmentedSubstring>::const_iterator e = m_substrings.end();
36         for (; it != e; ++it)
37             length += it->m_length;
38     }
39     return length;
40 }
41
42 void SegmentedString::setExcludeLineNumbers()
43 {
44     m_currentString.setExcludeLineNumbers();
45     if (isComposite()) {
46         Deque<SegmentedSubstring>::iterator it = m_substrings.begin();
47         Deque<SegmentedSubstring>::iterator e = m_substrings.end();
48         for (; it != e; ++it)
49             it->setExcludeLineNumbers();
50     }
51 }
52
53 void SegmentedString::clear()
54 {
55     m_pushedChar1 = 0;
56     m_pushedChar2 = 0;
57     m_currentChar = 0;
58     m_currentString.clear();
59     m_numberOfCharactersConsumedPriorToCurrentString = 0;
60     m_numberOfCharactersConsumedPriorToCurrentLine = 0;
61     m_currentLine = 0;
62     m_substrings.clear();
63     m_closed = false;
64     m_empty = true;
65     m_fastPathFlags = NoFastPath;
66     m_advanceFunc = &SegmentedString::advanceEmpty;
67     m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceEmpty;
68 }
69
70 void SegmentedString::append(const SegmentedSubstring& s)
71 {
72     ASSERT(!m_closed);
73     if (!s.m_length)
74         return;
75
76     if (!m_currentString.m_length) {
77         m_numberOfCharactersConsumedPriorToCurrentString += m_currentString.numberOfCharactersConsumed();
78         m_currentString = s;
79         updateAdvanceFunctionPointers();
80     } else {
81         m_substrings.append(s);
82     }
83     m_empty = false;
84 }
85
86 void SegmentedString::prepend(const SegmentedSubstring& s)
87 {
88     ASSERT(!escaped());
89     ASSERT(!s.numberOfCharactersConsumed());
90     if (!s.m_length)
91         return;
92
93     // FIXME: We're assuming that the prepend were originally consumed by
94     //        this SegmentedString. We're also ASSERTing that s is a fresh
95     //        SegmentedSubstring. These assumptions are sufficient for our
96     //        current use, but we might need to handle the more elaborate
97     //        cases in the future.
98     m_numberOfCharactersConsumedPriorToCurrentString += m_currentString.numberOfCharactersConsumed();
99     m_numberOfCharactersConsumedPriorToCurrentString -= s.m_length;
100     if (!m_currentString.m_length) {
101         m_currentString = s;
102         updateAdvanceFunctionPointers();
103     } else {
104         // Shift our m_currentString into our list.
105         m_substrings.prepend(m_currentString);
106         m_currentString = s;
107         updateAdvanceFunctionPointers();
108     }
109     m_empty = false;
110 }
111
112 void SegmentedString::close()
113 {
114     // Closing a stream twice is likely a coding mistake.
115     ASSERT(!m_closed);
116     m_closed = true;
117 }
118
119 void SegmentedString::append(const SegmentedString& s)
120 {
121     ASSERT(!m_closed);
122     if (s.m_pushedChar1) {
123         Vector<UChar, 2> unconsumedData;
124         unconsumedData.append(s.m_pushedChar1);
125         if (s.m_pushedChar2)
126             unconsumedData.append(s.m_pushedChar2);
127         append(SegmentedSubstring(String(unconsumedData)));
128     }
129
130     append(s.m_currentString);
131     if (s.isComposite()) {
132         Deque<SegmentedSubstring>::const_iterator it = s.m_substrings.begin();
133         Deque<SegmentedSubstring>::const_iterator e = s.m_substrings.end();
134         for (; it != e; ++it)
135             append(*it);
136     }
137     m_currentChar = m_pushedChar1 ? m_pushedChar1 : (m_currentString.m_length ? m_currentString.getCurrentChar() : 0);
138 }
139
140 void SegmentedString::prepend(const SegmentedString& s)
141 {
142     ASSERT(!escaped());
143     ASSERT(!s.escaped());
144     if (s.isComposite()) {
145         Deque<SegmentedSubstring>::const_reverse_iterator it = s.m_substrings.rbegin();
146         Deque<SegmentedSubstring>::const_reverse_iterator e = s.m_substrings.rend();
147         for (; it != e; ++it)
148             prepend(*it);
149     }
150     prepend(s.m_currentString);
151     m_currentChar = m_currentString.m_length ? m_currentString.getCurrentChar() : 0;
152 }
153
154 void SegmentedString::advanceSubstring()
155 {
156     if (isComposite()) {
157         m_numberOfCharactersConsumedPriorToCurrentString += m_currentString.numberOfCharactersConsumed();
158         m_currentString = m_substrings.takeFirst();
159         // If we've previously consumed some characters of the non-current
160         // string, we now account for those characters as part of the current
161         // string, not as part of "prior to current string."
162         m_numberOfCharactersConsumedPriorToCurrentString -= m_currentString.numberOfCharactersConsumed();
163         updateAdvanceFunctionPointers();
164     } else {
165         m_currentString.clear();
166         m_empty = true;
167         m_fastPathFlags = NoFastPath;
168         m_advanceFunc = &SegmentedString::advanceEmpty;
169         m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceEmpty;
170     }
171 }
172
173 String SegmentedString::toString() const
174 {
175     StringBuilder result;
176     if (m_pushedChar1) {
177         result.append(m_pushedChar1);
178         if (m_pushedChar2)
179             result.append(m_pushedChar2);
180     }
181     m_currentString.appendTo(result);
182     if (isComposite()) {
183         Deque<SegmentedSubstring>::const_iterator it = m_substrings.begin();
184         Deque<SegmentedSubstring>::const_iterator e = m_substrings.end();
185         for (; it != e; ++it)
186             it->appendTo(result);
187     }
188     return result.toString();
189 }
190
191 void SegmentedString::advance(unsigned count, UChar* consumedCharacters)
192 {
193     ASSERT_WITH_SECURITY_IMPLICATION(count <= length());
194     for (unsigned i = 0; i < count; ++i) {
195         consumedCharacters[i] = currentChar();
196         advance();
197     }
198 }
199
200 void SegmentedString::advance8()
201 {
202     ASSERT(!m_pushedChar1);
203     decrementAndCheckLength();
204     m_currentChar = m_currentString.incrementAndGetCurrentChar8();
205 }
206
207 void SegmentedString::advance16()
208 {
209     ASSERT(!m_pushedChar1);
210     decrementAndCheckLength();
211     m_currentChar = m_currentString.incrementAndGetCurrentChar16();
212 }
213
214 void SegmentedString::advanceAndUpdateLineNumber8()
215 {
216     ASSERT(!m_pushedChar1);
217     ASSERT(m_currentString.getCurrentChar() == m_currentChar);
218     if (m_currentChar == '\n') {
219         ++m_currentLine;
220         m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1;
221     }
222     decrementAndCheckLength();
223     m_currentChar = m_currentString.incrementAndGetCurrentChar8();
224 }
225
226 void SegmentedString::advanceAndUpdateLineNumber16()
227 {
228     ASSERT(!m_pushedChar1);
229     ASSERT(m_currentString.getCurrentChar() == m_currentChar);
230     if (m_currentChar == '\n') {
231         ++m_currentLine;
232         m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1;
233     }
234     decrementAndCheckLength();
235     m_currentChar = m_currentString.incrementAndGetCurrentChar16();
236 }
237
238 void SegmentedString::advanceSlowCase()
239 {
240     if (m_pushedChar1) {
241         m_pushedChar1 = m_pushedChar2;
242         m_pushedChar2 = 0;
243
244         if (m_pushedChar1) {
245             m_currentChar = m_pushedChar1;
246             return;
247         }
248
249         updateAdvanceFunctionPointers();
250     } else if (m_currentString.m_length) {
251         if (!--m_currentString.m_length)
252             advanceSubstring();
253     } else if (!isComposite()) {
254         m_currentString.clear();
255         m_empty = true;
256         m_fastPathFlags = NoFastPath;
257         m_advanceFunc = &SegmentedString::advanceEmpty;
258         m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceEmpty;
259     }
260     m_currentChar = m_currentString.m_length ? m_currentString.getCurrentChar() : 0;
261 }
262
263 void SegmentedString::advanceAndUpdateLineNumberSlowCase()
264 {
265     if (m_pushedChar1) {
266         m_pushedChar1 = m_pushedChar2;
267         m_pushedChar2 = 0;
268
269         if (m_pushedChar1) {
270             m_currentChar = m_pushedChar1;
271             return;
272         }
273
274         updateAdvanceFunctionPointers();
275     } else if (m_currentString.m_length) {
276         if (m_currentString.getCurrentChar() == '\n' && m_currentString.doNotExcludeLineNumbers()) {
277             ++m_currentLine;
278             // Plus 1 because numberOfCharactersConsumed value hasn't incremented yet; it does with m_length decrement below.
279             m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1;
280         }
281         if (!--m_currentString.m_length)
282             advanceSubstring();
283         else
284             m_currentString.incrementAndGetCurrentChar(); // Only need the ++
285     } else if (!isComposite()) {
286         m_currentString.clear();
287         m_empty = true;
288         m_fastPathFlags = NoFastPath;
289         m_advanceFunc = &SegmentedString::advanceEmpty;
290         m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceEmpty;
291     }
292
293     m_currentChar = m_currentString.m_length ? m_currentString.getCurrentChar() : 0;
294 }
295
296 void SegmentedString::advanceEmpty()
297 {
298     ASSERT(!m_currentString.m_length && !isComposite());
299     m_currentChar = 0;
300 }
301
302 void SegmentedString::updateSlowCaseFunctionPointers()
303 {
304     m_fastPathFlags = NoFastPath;
305     m_advanceFunc = &SegmentedString::advanceSlowCase;
306     m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceAndUpdateLineNumberSlowCase;
307 }
308
309 OrdinalNumber SegmentedString::currentLine() const
310 {
311     return OrdinalNumber::fromZeroBasedInt(m_currentLine);
312 }
313
314 OrdinalNumber SegmentedString::currentColumn() const
315 {
316     int zeroBasedColumn = numberOfCharactersConsumed() - m_numberOfCharactersConsumedPriorToCurrentLine;
317     return OrdinalNumber::fromZeroBasedInt(zeroBasedColumn);
318 }
319
320 void SegmentedString::setCurrentPosition(OrdinalNumber line, OrdinalNumber columnAftreProlog, int prologLength)
321 {
322     m_currentLine = line.zeroBasedInt();
323     m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + prologLength - columnAftreProlog.zeroBasedInt();
324 }
325
326 }