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 25 SegmentedString::SegmentedString(const SegmentedString& other) 26 : m_pushedChar1(other.m_pushedChar1) 27 , m_pushedChar2(other.m_pushedChar2) 28 , m_currentString(other.m_currentString) 29 , m_substrings(other.m_substrings) 30 , m_closed(other.m_closed) 31 { 32 if (other.m_currentChar == &other.m_pushedChar1) 33 m_currentChar = &m_pushedChar1; 34 else if (other.m_currentChar == &other.m_pushedChar2) 35 m_currentChar = &m_pushedChar2; 36 else 37 m_currentChar = other.m_currentChar; 38 } 39 40 const SegmentedString& SegmentedString::operator=(const SegmentedString& other) 41 { 42 m_pushedChar1 = other.m_pushedChar1; 43 m_pushedChar2 = other.m_pushedChar2; 44 m_currentString = other.m_currentString; 45 m_substrings = other.m_substrings; 46 if (other.m_currentChar == &other.m_pushedChar1) 47 m_currentChar = &m_pushedChar1; 48 else if (other.m_currentChar == &other.m_pushedChar2) 49 m_currentChar = &m_pushedChar2; 50 else 51 m_currentChar = other.m_currentChar; 52 m_closed = other.m_closed; 53 m_numberOfCharactersConsumedPriorToCurrentString = other.m_numberOfCharactersConsumedPriorToCurrentString; 54 m_numberOfCharactersConsumedPriorToCurrentLine = other.m_numberOfCharactersConsumedPriorToCurrentLine; 55 m_currentLine = other.m_currentLine; 56 57 return *this; 58 } 59 60 unsigned SegmentedString::length() const 61 { 62 unsigned length = m_currentString.m_length; 63 if (m_pushedChar1) { 64 ++length; 65 if (m_pushedChar2) 66 ++length; 67 } 68 if (isComposite()) { 69 Deque<SegmentedSubstring>::const_iterator it = m_substrings.begin(); 70 Deque<SegmentedSubstring>::const_iterator e = m_substrings.end(); 71 for (; it != e; ++it) 72 length += it->m_length; 73 } 74 return length; 75 } 76 77 void SegmentedString::setExcludeLineNumbers() 78 { 79 m_currentString.setExcludeLineNumbers(); 80 if (isComposite()) { 81 Deque<SegmentedSubstring>::iterator it = m_substrings.begin(); 82 Deque<SegmentedSubstring>::iterator e = m_substrings.end(); 83 for (; it != e; ++it) 84 it->setExcludeLineNumbers(); 85 } 86 } 87 88 void SegmentedString::clear() 89 { 90 m_pushedChar1 = 0; 91 m_pushedChar2 = 0; 92 m_currentChar = 0; 93 m_currentString.clear(); 94 m_substrings.clear(); 95 m_closed = false; 96 } 97 98 void SegmentedString::append(const SegmentedSubstring& s) 99 { 100 ASSERT(!m_closed); 101 if (!s.m_length) 102 return; 103 104 if (!m_currentString.m_length) { 105 m_numberOfCharactersConsumedPriorToCurrentString += m_currentString.numberOfCharactersConsumed(); 106 m_currentString = s; 107 } else 108 m_substrings.append(s); 109 } 110 111 void SegmentedString::prepend(const SegmentedSubstring& s) 112 { 113 ASSERT(!escaped()); 114 ASSERT(!s.numberOfCharactersConsumed()); 115 if (!s.m_length) 116 return; 117 118 // FIXME: We're assuming that the prepend were originally consumed by 119 // this SegmentedString. We're also ASSERTing that s is a fresh 120 // SegmentedSubstring. These assumptions are sufficient for our 121 // current use, but we might need to handle the more elaborate 122 // cases in the future. 123 m_numberOfCharactersConsumedPriorToCurrentString += m_currentString.numberOfCharactersConsumed(); 124 m_numberOfCharactersConsumedPriorToCurrentString -= s.m_length; 125 if (!m_currentString.m_length) 126 m_currentString = s; 127 else { 128 // Shift our m_currentString into our list. 129 m_substrings.prepend(m_currentString); 130 m_currentString = s; 131 } 132 } 133 134 void SegmentedString::close() 135 { 136 // Closing a stream twice is likely a coding mistake. 137 ASSERT(!m_closed); 138 m_closed = true; 139 } 140 141 void SegmentedString::append(const SegmentedString& s) 142 { 143 ASSERT(!m_closed); 144 ASSERT(!s.escaped()); 145 append(s.m_currentString); 146 if (s.isComposite()) { 147 Deque<SegmentedSubstring>::const_iterator it = s.m_substrings.begin(); 148 Deque<SegmentedSubstring>::const_iterator e = s.m_substrings.end(); 149 for (; it != e; ++it) 150 append(*it); 151 } 152 m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current; 153 } 154 155 void SegmentedString::prepend(const SegmentedString& s) 156 { 157 ASSERT(!escaped()); 158 ASSERT(!s.escaped()); 159 if (s.isComposite()) { 160 Deque<SegmentedSubstring>::const_reverse_iterator it = s.m_substrings.rbegin(); 161 Deque<SegmentedSubstring>::const_reverse_iterator e = s.m_substrings.rend(); 162 for (; it != e; ++it) 163 prepend(*it); 164 } 165 prepend(s.m_currentString); 166 m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current; 167 } 168 169 void SegmentedString::advanceSubstring() 170 { 171 if (isComposite()) { 172 m_numberOfCharactersConsumedPriorToCurrentString += m_currentString.numberOfCharactersConsumed(); 173 m_currentString = m_substrings.takeFirst(); 174 // If we've previously consumed some characters of the non-current 175 // string, we now account for those characters as part of the current 176 // string, not as part of "prior to current string." 177 m_numberOfCharactersConsumedPriorToCurrentString -= m_currentString.numberOfCharactersConsumed(); 178 } else 179 m_currentString.clear(); 180 } 181 182 String SegmentedString::toString() const 183 { 184 String result; 185 if (m_pushedChar1) { 186 result.append(m_pushedChar1); 187 if (m_pushedChar2) 188 result.append(m_pushedChar2); 189 } 190 m_currentString.appendTo(result); 191 if (isComposite()) { 192 Deque<SegmentedSubstring>::const_iterator it = m_substrings.begin(); 193 Deque<SegmentedSubstring>::const_iterator e = m_substrings.end(); 194 for (; it != e; ++it) 195 it->appendTo(result); 196 } 197 return result; 198 } 199 200 void SegmentedString::advance(unsigned count, UChar* consumedCharacters) 201 { 202 ASSERT(count <= length()); 203 for (unsigned i = 0; i < count; ++i) { 204 consumedCharacters[i] = *current(); 205 advance(); 206 } 207 } 208 209 void SegmentedString::advanceSlowCase() 210 { 211 if (m_pushedChar1) { 212 m_pushedChar1 = m_pushedChar2; 213 m_pushedChar2 = 0; 214 } else if (m_currentString.m_current) { 215 ++m_currentString.m_current; 216 if (--m_currentString.m_length == 0) 217 advanceSubstring(); 218 } 219 m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current; 220 } 221 222 void SegmentedString::advanceSlowCase(int& lineNumber) 223 { 224 if (m_pushedChar1) { 225 m_pushedChar1 = m_pushedChar2; 226 m_pushedChar2 = 0; 227 } else if (m_currentString.m_current) { 228 if (*m_currentString.m_current++ == '\n' && m_currentString.doNotExcludeLineNumbers()) { 229 ++lineNumber; 230 ++m_currentLine; 231 // Plus 1 because numberOfCharactersConsumed value hasn't incremented yet; it does with m_length decrement below. 232 m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1; 233 } 234 if (--m_currentString.m_length == 0) 235 advanceSubstring(); 236 } 237 m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current; 238 } 239 240 WTF::ZeroBasedNumber SegmentedString::currentLine() const 241 { 242 return WTF::ZeroBasedNumber::fromZeroBasedInt(m_currentLine); 243 } 244 245 WTF::ZeroBasedNumber SegmentedString::currentColumn() const 246 { 247 int zeroBasedColumn = numberOfCharactersConsumed() - m_numberOfCharactersConsumedPriorToCurrentLine; 248 return WTF::ZeroBasedNumber::fromZeroBasedInt(zeroBasedColumn); 249 } 250 251 void SegmentedString::setCurrentPosition(WTF::ZeroBasedNumber line, WTF::ZeroBasedNumber columnAftreProlog, int prologLength) 252 { 253 m_currentLine = line.zeroBasedInt(); 254 m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + prologLength - columnAftreProlog.zeroBasedInt(); 255 } 256 257 } 258