/*
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 <wtf/Deque.h>
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<SegmentedSubstring> m_substrings;
bool m_composite;
};
}
#endif