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 #ifndef SegmentedString_h 21 #define SegmentedString_h 22 23 #include "PlatformString.h" 24 #include <wtf/Deque.h> 25 26 namespace WebCore { 27 28 class SegmentedString; 29 30 class SegmentedSubstring { 31 public: SegmentedSubstring()32 SegmentedSubstring() : m_length(0), m_current(0), m_doNotExcludeLineNumbers(true) {} SegmentedSubstring(const String & str)33 SegmentedSubstring(const String& str) 34 : m_length(str.length()) 35 , m_current(str.isEmpty() ? 0 : str.characters()) 36 , m_string(str) 37 , m_doNotExcludeLineNumbers(true) 38 { 39 } 40 SegmentedSubstring(const UChar * str,int length)41 SegmentedSubstring(const UChar* str, int length) : m_length(length), m_current(length == 0 ? 0 : str), m_doNotExcludeLineNumbers(true) {} 42 clear()43 void clear() { m_length = 0; m_current = 0; } 44 excludeLineNumbers()45 bool excludeLineNumbers() const { return !m_doNotExcludeLineNumbers; } doNotExcludeLineNumbers()46 bool doNotExcludeLineNumbers() const { return m_doNotExcludeLineNumbers; } 47 setExcludeLineNumbers()48 void setExcludeLineNumbers() { m_doNotExcludeLineNumbers = false; } 49 appendTo(String & str)50 void appendTo(String& str) const 51 { 52 if (m_string.characters() == m_current) { 53 if (str.isEmpty()) 54 str = m_string; 55 else 56 str.append(m_string); 57 } else { 58 str.append(String(m_current, m_length)); 59 } 60 } 61 62 public: 63 int m_length; 64 const UChar* m_current; 65 66 private: 67 String m_string; 68 bool m_doNotExcludeLineNumbers; 69 }; 70 71 class SegmentedString { 72 public: SegmentedString()73 SegmentedString() 74 : m_pushedChar1(0), m_pushedChar2(0), m_currentChar(0), m_composite(false) {} SegmentedString(const UChar * str,int length)75 SegmentedString(const UChar* str, int length) : m_pushedChar1(0), m_pushedChar2(0) 76 , m_currentString(str, length), m_currentChar(m_currentString.m_current), m_composite(false) {} SegmentedString(const String & str)77 SegmentedString(const String& str) 78 : m_pushedChar1(0), m_pushedChar2(0), m_currentString(str) 79 , m_currentChar(m_currentString.m_current), m_composite(false) {} 80 SegmentedString(const SegmentedString&); 81 82 const SegmentedString& operator=(const SegmentedString&); 83 84 void clear(); 85 86 void append(const SegmentedString&); 87 void prepend(const SegmentedString&); 88 excludeLineNumbers()89 bool excludeLineNumbers() const { return m_currentString.excludeLineNumbers(); } 90 void setExcludeLineNumbers(); 91 push(UChar c)92 void push(UChar c) 93 { 94 if (!m_pushedChar1) { 95 m_pushedChar1 = c; 96 m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current; 97 } else { 98 ASSERT(!m_pushedChar2); 99 m_pushedChar2 = c; 100 } 101 } 102 isEmpty()103 bool isEmpty() const { return !current(); } 104 unsigned length() const; 105 advance()106 void advance() 107 { 108 if (!m_pushedChar1 && m_currentString.m_length > 1) { 109 --m_currentString.m_length; 110 m_currentChar = ++m_currentString.m_current; 111 return; 112 } 113 advanceSlowCase(); 114 } 115 advancePastNewline(int & lineNumber)116 void advancePastNewline(int& lineNumber) 117 { 118 ASSERT(*current() == '\n'); 119 if (!m_pushedChar1 && m_currentString.m_length > 1) { 120 lineNumber += m_currentString.doNotExcludeLineNumbers(); 121 --m_currentString.m_length; 122 m_currentChar = ++m_currentString.m_current; 123 return; 124 } 125 advanceSlowCase(lineNumber); 126 } 127 advancePastNonNewline()128 void advancePastNonNewline() 129 { 130 ASSERT(*current() != '\n'); 131 if (!m_pushedChar1 && m_currentString.m_length > 1) { 132 --m_currentString.m_length; 133 m_currentChar = ++m_currentString.m_current; 134 return; 135 } 136 advanceSlowCase(); 137 } 138 advance(int & lineNumber)139 void advance(int& lineNumber) 140 { 141 if (!m_pushedChar1 && m_currentString.m_length > 1) { 142 lineNumber += (*m_currentString.m_current == '\n') & m_currentString.doNotExcludeLineNumbers(); 143 --m_currentString.m_length; 144 m_currentChar = ++m_currentString.m_current; 145 return; 146 } 147 advanceSlowCase(lineNumber); 148 } 149 escaped()150 bool escaped() const { return m_pushedChar1; } 151 152 String toString() const; 153 154 const UChar& operator*() const { return *current(); } 155 const UChar* operator->() const { return current(); } 156 157 private: 158 void append(const SegmentedSubstring&); 159 void prepend(const SegmentedSubstring&); 160 161 void advanceSlowCase(); 162 void advanceSlowCase(int& lineNumber); 163 void advanceSubstring(); current()164 const UChar* current() const { return m_currentChar; } 165 166 UChar m_pushedChar1; 167 UChar m_pushedChar2; 168 SegmentedSubstring m_currentString; 169 const UChar* m_currentChar; 170 Deque<SegmentedSubstring> m_substrings; 171 bool m_composite; 172 }; 173 174 } 175 176 #endif 177