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 #include "config.h"
     21 #include "SegmentedString.h"
     22 
     23 namespace WebCore {
     24 
     25 SegmentedString::SegmentedString(const SegmentedString& other)
     26     : m_pushedChar1(other.m_pushedChar1)
     27     , m_pushedChar2(other.m_pushedChar2)
     28     , m_currentString(other.m_currentString)
     29     , m_substrings(other.m_substrings)
     30     , m_closed(other.m_closed)
     31 {
     32     if (other.m_currentChar == &other.m_pushedChar1)
     33         m_currentChar = &m_pushedChar1;
     34     else if (other.m_currentChar == &other.m_pushedChar2)
     35         m_currentChar = &m_pushedChar2;
     36     else
     37         m_currentChar = other.m_currentChar;
     38 }
     39 
     40 const SegmentedString& SegmentedString::operator=(const SegmentedString& other)
     41 {
     42     m_pushedChar1 = other.m_pushedChar1;
     43     m_pushedChar2 = other.m_pushedChar2;
     44     m_currentString = other.m_currentString;
     45     m_substrings = other.m_substrings;
     46     if (other.m_currentChar == &other.m_pushedChar1)
     47         m_currentChar = &m_pushedChar1;
     48     else if (other.m_currentChar == &other.m_pushedChar2)
     49         m_currentChar = &m_pushedChar2;
     50     else
     51         m_currentChar = other.m_currentChar;
     52     m_closed = other.m_closed;
     53     m_numberOfCharactersConsumedPriorToCurrentString = other.m_numberOfCharactersConsumedPriorToCurrentString;
     54     m_numberOfCharactersConsumedPriorToCurrentLine = other.m_numberOfCharactersConsumedPriorToCurrentLine;
     55     m_currentLine = other.m_currentLine;
     56 
     57     return *this;
     58 }
     59 
     60 unsigned SegmentedString::length() const
     61 {
     62     unsigned length = m_currentString.m_length;
     63     if (m_pushedChar1) {
     64         ++length;
     65         if (m_pushedChar2)
     66             ++length;
     67     }
     68     if (isComposite()) {
     69         Deque<SegmentedSubstring>::const_iterator it = m_substrings.begin();
     70         Deque<SegmentedSubstring>::const_iterator e = m_substrings.end();
     71         for (; it != e; ++it)
     72             length += it->m_length;
     73     }
     74     return length;
     75 }
     76 
     77 void SegmentedString::setExcludeLineNumbers()
     78 {
     79     m_currentString.setExcludeLineNumbers();
     80     if (isComposite()) {
     81         Deque<SegmentedSubstring>::iterator it = m_substrings.begin();
     82         Deque<SegmentedSubstring>::iterator e = m_substrings.end();
     83         for (; it != e; ++it)
     84             it->setExcludeLineNumbers();
     85     }
     86 }
     87 
     88 void SegmentedString::clear()
     89 {
     90     m_pushedChar1 = 0;
     91     m_pushedChar2 = 0;
     92     m_currentChar = 0;
     93     m_currentString.clear();
     94     m_substrings.clear();
     95     m_closed = false;
     96 }
     97 
     98 void SegmentedString::append(const SegmentedSubstring& s)
     99 {
    100     ASSERT(!m_closed);
    101     if (!s.m_length)
    102         return;
    103 
    104     if (!m_currentString.m_length) {
    105         m_numberOfCharactersConsumedPriorToCurrentString += m_currentString.numberOfCharactersConsumed();
    106         m_currentString = s;
    107     } else
    108         m_substrings.append(s);
    109 }
    110 
    111 void SegmentedString::prepend(const SegmentedSubstring& s)
    112 {
    113     ASSERT(!escaped());
    114     ASSERT(!s.numberOfCharactersConsumed());
    115     if (!s.m_length)
    116         return;
    117 
    118     // FIXME: We're assuming that the prepend were originally consumed by
    119     //        this SegmentedString.  We're also ASSERTing that s is a fresh
    120     //        SegmentedSubstring.  These assumptions are sufficient for our
    121     //        current use, but we might need to handle the more elaborate
    122     //        cases in the future.
    123     m_numberOfCharactersConsumedPriorToCurrentString += m_currentString.numberOfCharactersConsumed();
    124     m_numberOfCharactersConsumedPriorToCurrentString -= s.m_length;
    125     if (!m_currentString.m_length)
    126         m_currentString = s;
    127     else {
    128         // Shift our m_currentString into our list.
    129         m_substrings.prepend(m_currentString);
    130         m_currentString = s;
    131     }
    132 }
    133 
    134 void SegmentedString::close()
    135 {
    136     // Closing a stream twice is likely a coding mistake.
    137     ASSERT(!m_closed);
    138     m_closed = true;
    139 }
    140 
    141 void SegmentedString::append(const SegmentedString& s)
    142 {
    143     ASSERT(!m_closed);
    144     ASSERT(!s.escaped());
    145     append(s.m_currentString);
    146     if (s.isComposite()) {
    147         Deque<SegmentedSubstring>::const_iterator it = s.m_substrings.begin();
    148         Deque<SegmentedSubstring>::const_iterator e = s.m_substrings.end();
    149         for (; it != e; ++it)
    150             append(*it);
    151     }
    152     m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current;
    153 }
    154 
    155 void SegmentedString::prepend(const SegmentedString& s)
    156 {
    157     ASSERT(!escaped());
    158     ASSERT(!s.escaped());
    159     if (s.isComposite()) {
    160         Deque<SegmentedSubstring>::const_reverse_iterator it = s.m_substrings.rbegin();
    161         Deque<SegmentedSubstring>::const_reverse_iterator e = s.m_substrings.rend();
    162         for (; it != e; ++it)
    163             prepend(*it);
    164     }
    165     prepend(s.m_currentString);
    166     m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current;
    167 }
    168 
    169 void SegmentedString::advanceSubstring()
    170 {
    171     if (isComposite()) {
    172         m_numberOfCharactersConsumedPriorToCurrentString += m_currentString.numberOfCharactersConsumed();
    173         m_currentString = m_substrings.takeFirst();
    174         // If we've previously consumed some characters of the non-current
    175         // string, we now account for those characters as part of the current
    176         // string, not as part of "prior to current string."
    177         m_numberOfCharactersConsumedPriorToCurrentString -= m_currentString.numberOfCharactersConsumed();
    178     } else
    179         m_currentString.clear();
    180 }
    181 
    182 String SegmentedString::toString() const
    183 {
    184     String result;
    185     if (m_pushedChar1) {
    186         result.append(m_pushedChar1);
    187         if (m_pushedChar2)
    188             result.append(m_pushedChar2);
    189     }
    190     m_currentString.appendTo(result);
    191     if (isComposite()) {
    192         Deque<SegmentedSubstring>::const_iterator it = m_substrings.begin();
    193         Deque<SegmentedSubstring>::const_iterator e = m_substrings.end();
    194         for (; it != e; ++it)
    195             it->appendTo(result);
    196     }
    197     return result;
    198 }
    199 
    200 void SegmentedString::advance(unsigned count, UChar* consumedCharacters)
    201 {
    202     ASSERT(count <= length());
    203     for (unsigned i = 0; i < count; ++i) {
    204         consumedCharacters[i] = *current();
    205         advance();
    206     }
    207 }
    208 
    209 void SegmentedString::advanceSlowCase()
    210 {
    211     if (m_pushedChar1) {
    212         m_pushedChar1 = m_pushedChar2;
    213         m_pushedChar2 = 0;
    214     } else if (m_currentString.m_current) {
    215         ++m_currentString.m_current;
    216         if (--m_currentString.m_length == 0)
    217             advanceSubstring();
    218     }
    219     m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current;
    220 }
    221 
    222 void SegmentedString::advanceSlowCase(int& lineNumber)
    223 {
    224     if (m_pushedChar1) {
    225         m_pushedChar1 = m_pushedChar2;
    226         m_pushedChar2 = 0;
    227     } else if (m_currentString.m_current) {
    228         if (*m_currentString.m_current++ == '\n' && m_currentString.doNotExcludeLineNumbers()) {
    229             ++lineNumber;
    230             ++m_currentLine;
    231             // Plus 1 because numberOfCharactersConsumed value hasn't incremented yet; it does with m_length decrement below.
    232             m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1;
    233         }
    234         if (--m_currentString.m_length == 0)
    235             advanceSubstring();
    236     }
    237     m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current;
    238 }
    239 
    240 WTF::ZeroBasedNumber SegmentedString::currentLine() const
    241 {
    242     return WTF::ZeroBasedNumber::fromZeroBasedInt(m_currentLine);
    243 }
    244 
    245 WTF::ZeroBasedNumber SegmentedString::currentColumn() const
    246 {
    247     int zeroBasedColumn = numberOfCharactersConsumed() - m_numberOfCharactersConsumedPriorToCurrentLine;
    248     return WTF::ZeroBasedNumber::fromZeroBasedInt(zeroBasedColumn);
    249 }
    250 
    251 void SegmentedString::setCurrentPosition(WTF::ZeroBasedNumber line, WTF::ZeroBasedNumber columnAftreProlog, int prologLength)
    252 {
    253     m_currentLine = line.zeroBasedInt();
    254     m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + prologLength - columnAftreProlog.zeroBasedInt();
    255 }
    256 
    257 }
    258