• 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 #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