/* Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef SegmentedString_h #define SegmentedString_h #include "PlatformString.h" #include namespace WebCore { class SegmentedString; class SegmentedSubstring { public: SegmentedSubstring() : m_length(0), m_current(0), m_doNotExcludeLineNumbers(true) {} SegmentedSubstring(const String& str) : m_length(str.length()) , m_current(str.isEmpty() ? 0 : str.characters()) , m_string(str) , m_doNotExcludeLineNumbers(true) { } SegmentedSubstring(const UChar* str, int length) : m_length(length), m_current(length == 0 ? 0 : str), m_doNotExcludeLineNumbers(true) {} void clear() { m_length = 0; m_current = 0; } bool excludeLineNumbers() const { return !m_doNotExcludeLineNumbers; } bool doNotExcludeLineNumbers() const { return m_doNotExcludeLineNumbers; } void setExcludeLineNumbers() { m_doNotExcludeLineNumbers = false; } void appendTo(String& str) const { if (m_string.characters() == m_current) { if (str.isEmpty()) str = m_string; else str.append(m_string); } else { str.append(String(m_current, m_length)); } } public: int m_length; const UChar* m_current; private: String m_string; bool m_doNotExcludeLineNumbers; }; class SegmentedString { public: SegmentedString() : m_pushedChar1(0), m_pushedChar2(0), m_currentChar(0), m_composite(false) {} SegmentedString(const UChar* str, int length) : m_pushedChar1(0), m_pushedChar2(0) , m_currentString(str, length), m_currentChar(m_currentString.m_current), m_composite(false) {} SegmentedString(const String& str) : m_pushedChar1(0), m_pushedChar2(0), m_currentString(str) , m_currentChar(m_currentString.m_current), m_composite(false) {} SegmentedString(const SegmentedString&); const SegmentedString& operator=(const SegmentedString&); void clear(); void append(const SegmentedString&); void prepend(const SegmentedString&); bool excludeLineNumbers() const { return m_currentString.excludeLineNumbers(); } void setExcludeLineNumbers(); void push(UChar c) { if (!m_pushedChar1) { m_pushedChar1 = c; m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current; } else { ASSERT(!m_pushedChar2); m_pushedChar2 = c; } } bool isEmpty() const { return !current(); } unsigned length() const; void advance() { if (!m_pushedChar1 && m_currentString.m_length > 1) { --m_currentString.m_length; m_currentChar = ++m_currentString.m_current; return; } advanceSlowCase(); } void advancePastNewline(int& lineNumber) { ASSERT(*current() == '\n'); if (!m_pushedChar1 && m_currentString.m_length > 1) { lineNumber += m_currentString.doNotExcludeLineNumbers(); --m_currentString.m_length; m_currentChar = ++m_currentString.m_current; return; } advanceSlowCase(lineNumber); } void advancePastNonNewline() { ASSERT(*current() != '\n'); if (!m_pushedChar1 && m_currentString.m_length > 1) { --m_currentString.m_length; m_currentChar = ++m_currentString.m_current; return; } advanceSlowCase(); } void advance(int& lineNumber) { if (!m_pushedChar1 && m_currentString.m_length > 1) { lineNumber += (*m_currentString.m_current == '\n') & m_currentString.doNotExcludeLineNumbers(); --m_currentString.m_length; m_currentChar = ++m_currentString.m_current; return; } advanceSlowCase(lineNumber); } bool escaped() const { return m_pushedChar1; } String toString() const; const UChar& operator*() const { return *current(); } const UChar* operator->() const { return current(); } private: void append(const SegmentedSubstring&); void prepend(const SegmentedSubstring&); void advanceSlowCase(); void advanceSlowCase(int& lineNumber); void advanceSubstring(); const UChar* current() const { return m_currentChar; } UChar m_pushedChar1; UChar m_pushedChar2; SegmentedSubstring m_currentString; const UChar* m_currentChar; Deque m_substrings; bool m_composite; }; } #endif