• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "SegmentedString.h"
22 
23 namespace WebCore {
24 
SegmentedString(const SegmentedString & other)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 
operator =(const SegmentedString & other)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 
length() const53 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         Deque<SegmentedSubstring>::const_iterator it = m_substrings.begin();
63         Deque<SegmentedSubstring>::const_iterator e = m_substrings.end();
64         for (; it != e; ++it)
65             length += it->m_length;
66     }
67     return length;
68 }
69 
setExcludeLineNumbers()70 void SegmentedString::setExcludeLineNumbers()
71 {
72     if (m_composite) {
73         Deque<SegmentedSubstring>::iterator it = m_substrings.begin();
74         Deque<SegmentedSubstring>::iterator e = m_substrings.end();
75         for (; it != e; ++it)
76             it->setExcludeLineNumbers();
77     } else
78         m_currentString.setExcludeLineNumbers();
79 }
80 
clear()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 
append(const SegmentedSubstring & s)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 
prepend(const SegmentedSubstring & s)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 
append(const SegmentedString & s)118 void SegmentedString::append(const SegmentedString &s)
119 {
120     ASSERT(!s.escaped());
121     append(s.m_currentString);
122     if (s.m_composite) {
123         Deque<SegmentedSubstring>::const_iterator it = s.m_substrings.begin();
124         Deque<SegmentedSubstring>::const_iterator e = s.m_substrings.end();
125         for (; it != e; ++it)
126             append(*it);
127     }
128     m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current;
129 }
130 
prepend(const SegmentedString & s)131 void SegmentedString::prepend(const SegmentedString &s)
132 {
133     ASSERT(!escaped());
134     ASSERT(!s.escaped());
135     if (s.m_composite) {
136         Deque<SegmentedSubstring>::const_reverse_iterator it = s.m_substrings.rbegin();
137         Deque<SegmentedSubstring>::const_reverse_iterator e = s.m_substrings.rend();
138         for (; it != e; ++it)
139             prepend(*it);
140     }
141     prepend(s.m_currentString);
142     m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current;
143 }
144 
advanceSubstring()145 void SegmentedString::advanceSubstring()
146 {
147     if (m_composite) {
148         m_currentString = m_substrings.first();
149         m_substrings.removeFirst();
150         if (m_substrings.isEmpty())
151             m_composite = false;
152     } else {
153         m_currentString.clear();
154     }
155 }
156 
toString() const157 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         Deque<SegmentedSubstring>::const_iterator it = m_substrings.begin();
168         Deque<SegmentedSubstring>::const_iterator e = m_substrings.end();
169         for (; it != e; ++it)
170             it->appendTo(result);
171     }
172     return result;
173 }
174 
advanceSlowCase()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 
advanceSlowCase(int & lineNumber)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.doNotExcludeLineNumbers())
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 }
203