Home | History | Annotate | Download | only in text
      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:
     32     SegmentedSubstring() : m_length(0), m_current(0), m_doNotExcludeLineNumbers(true) {}
     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 
     41     SegmentedSubstring(const UChar* str, int length) : m_length(length), m_current(length == 0 ? 0 : str), m_doNotExcludeLineNumbers(true) {}
     42 
     43     void clear() { m_length = 0; m_current = 0; }
     44 
     45     bool excludeLineNumbers() const { return !m_doNotExcludeLineNumbers; }
     46     bool doNotExcludeLineNumbers() const { return m_doNotExcludeLineNumbers; }
     47 
     48     void setExcludeLineNumbers() { m_doNotExcludeLineNumbers = false; }
     49 
     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:
     73     SegmentedString()
     74         : m_pushedChar1(0), m_pushedChar2(0), m_currentChar(0), m_composite(false) {}
     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) {}
     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 
     89     bool excludeLineNumbers() const { return m_currentString.excludeLineNumbers(); }
     90     void setExcludeLineNumbers();
     91 
     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 
    103     bool isEmpty() const { return !current(); }
    104     unsigned length() const;
    105 
    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 
    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 
    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 
    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 
    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();
    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