Reviewed by Mitz.
[WebKit-https.git] / WebCore / platform / SegmentedString.h
1 /*
2     Copyright (C) 2004, 2005, 2006, 2007 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 "DeprecatedValueList.h"
24 #include "PlatformString.h"
25
26 namespace WebCore {
27
28 class SegmentedString;
29
30 class SegmentedSubstring {
31 private:
32     friend class SegmentedString;
33     
34     SegmentedSubstring() : m_length(0), m_current(0), m_excludeLineNumbers(false) {}
35     SegmentedSubstring(const String& str) : m_string(str), m_length(str.length()), m_excludeLineNumbers(false) {
36         m_current = m_length == 0 ? 0 : m_string.characters();
37     }
38
39     SegmentedSubstring(const UChar* str, int length) : m_length(length), m_current(length == 0 ? 0 : str), m_excludeLineNumbers(false) {}
40
41     void clear() { m_length = 0; m_current = 0; }
42     
43     bool excludeLineNumbers() const { return m_excludeLineNumbers; }
44     void setExcludeLineNumbers() { m_excludeLineNumbers = true; }
45
46     void appendTo(String& str) const {
47         if (m_string.characters() == m_current) {
48             if (str.isEmpty())
49                 str = m_string;
50             else
51                 str.append(m_string);
52         } else {
53             str.append(String(m_current, m_length));
54         }
55     }
56
57     String m_string;
58     int m_length;
59     const UChar* m_current;
60     bool m_excludeLineNumbers;
61 };
62
63 class SegmentedString {
64 public:
65     SegmentedString()
66         : m_pushedChar1(0), m_pushedChar2(0), m_currentChar(0), m_composite(false) {}
67     SegmentedString(const UChar* str, int length) : m_pushedChar1(0), m_pushedChar2(0)
68         , m_currentString(str, length), m_currentChar(m_currentString.m_current), m_composite(false) {}
69     SegmentedString(const String& str)
70         : m_pushedChar1(0), m_pushedChar2(0), m_currentString(str)
71         , m_currentChar(m_currentString.m_current), m_composite(false) {}
72     SegmentedString(const SegmentedString&);
73
74     const SegmentedString& operator=(const SegmentedString&);
75
76     void clear();
77
78     void append(const SegmentedString &);
79     void prepend(const SegmentedString &);
80     
81     bool excludeLineNumbers() const { return m_currentString.excludeLineNumbers(); }
82     void setExcludeLineNumbers();
83
84     void push(UChar c)
85     {
86         if (!m_pushedChar1) {
87             m_pushedChar1 = c;
88             m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current;
89         } else {
90             ASSERT(!m_pushedChar2);
91             m_pushedChar2 = c;
92         }
93     }
94     
95     bool isEmpty() const { return !current(); }
96     unsigned length() const;
97
98     void advance()
99     {
100         if (!m_pushedChar1 && m_currentString.m_length > 1) {
101             --m_currentString.m_length;
102             m_currentChar = ++m_currentString.m_current;
103             return;
104         }
105         advanceSlowCase();
106     }
107     
108     void advance(int& lineNumber)
109     {
110         if (!m_pushedChar1 && m_currentString.m_length > 1) {
111             lineNumber += (*m_currentString.m_current == '\n') & m_currentString.excludeLineNumbers();
112             --m_currentString.m_length;
113             m_currentChar = ++m_currentString.m_current;
114             return;
115         }
116         advanceSlowCase(lineNumber);
117     }
118     
119     bool escaped() const { return m_pushedChar1; }
120     
121     String toString() const;
122
123     const UChar& operator*() const { return *current(); }
124     const UChar* operator->() const { return current(); }
125     
126 private:
127     void append(const SegmentedSubstring &);
128     void prepend(const SegmentedSubstring &);
129
130     void advanceSlowCase();
131     void advanceSlowCase(int& lineNumber);
132     void advanceSubstring();
133     const UChar* current() const { return m_currentChar; }
134
135     UChar m_pushedChar1;
136     UChar m_pushedChar2;
137     SegmentedSubstring m_currentString;
138     const UChar* m_currentChar;
139     DeprecatedValueList<SegmentedSubstring> m_substrings;
140     bool m_composite;
141 };
142
143 }
144
145 #endif