/*
    This file is part of the KDE libraries

    Copyright (C) 2004, 2005, 2006 Apple Computer

    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 "DeprecatedValueList.h"
#include "PlatformString.h"

namespace WebCore {

class SegmentedString;

class SegmentedSubstring {
private:
    friend class SegmentedString;
    
    SegmentedSubstring() : m_length(0), m_current(0), m_excludeLineNumbers(false) {}
    SegmentedSubstring(const String& str) : m_string(str), m_length(str.length()), m_excludeLineNumbers(false) {
        m_current = m_length == 0 ? 0 : m_string.characters();
    }

    SegmentedSubstring(const UChar* str, int length) : m_length(length), m_current(length == 0 ? 0 : str), m_excludeLineNumbers(false) {}

    void clear() { m_length = 0; m_current = 0; }
    
    bool excludeLineNumbers() const { return m_excludeLineNumbers; }
    void setExcludeLineNumbers() { m_excludeLineNumbers = true; }

    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));
        }
    }

    String m_string;
    int m_length;
    const UChar* m_current;
    bool m_excludeLineNumbers;
};

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(int* lineNumber = 0) {
        if (m_pushedChar1) {
            m_pushedChar1 = m_pushedChar2;
            m_pushedChar2 = 0;
        } else if (m_currentString.m_current) {
            if (*m_currentString.m_current++ == '\n' && lineNumber && !m_currentString.excludeLineNumbers())
                *lineNumber = *lineNumber + 1;
            if (--m_currentString.m_length == 0)
                advanceSubstring();
        }
        m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current;
    }
    
    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 advanceSubstring();
    const UChar* current() const { return m_currentChar; }

    UChar m_pushedChar1;
    UChar m_pushedChar2;
    SegmentedSubstring m_currentString;
    const UChar* m_currentChar;
    DeprecatedValueList<SegmentedSubstring> m_substrings;
    bool m_composite;
};

}

#endif
