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 "core/platform/text/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_numberOfCharactersConsumedPriorToCurrentString(other.m_numberOfCharactersConsumedPriorToCurrentString)
     30     , m_numberOfCharactersConsumedPriorToCurrentLine(other.m_numberOfCharactersConsumedPriorToCurrentLine)
     31     , m_currentLine(other.m_currentLine)
     32     , m_substrings(other.m_substrings)
     33     , m_closed(other.m_closed)
     34     , m_empty(other.m_empty)
     35     , m_fastPathFlags(other.m_fastPathFlags)
     36     , m_advanceFunc(other.m_advanceFunc)
     37     , m_advanceAndUpdateLineNumberFunc(other.m_advanceAndUpdateLineNumberFunc)
     38 {
     39     if (m_pushedChar2)
     40         m_currentChar = m_pushedChar2;
     41     else if (m_pushedChar1)
     42         m_currentChar = m_pushedChar1;
     43     else
     44         m_currentChar = m_currentString.m_length ? m_currentString.getCurrentChar() : 0;
     45 }
     46 
     47 const SegmentedString& SegmentedString::operator=(const SegmentedString& other)
     48 {
     49     m_pushedChar1 = other.m_pushedChar1;
     50     m_pushedChar2 = other.m_pushedChar2;
     51     m_currentString = other.m_currentString;
     52     m_substrings = other.m_substrings;
     53     if (m_pushedChar2)
     54         m_currentChar = m_pushedChar2;
     55     else if (m_pushedChar1)
     56         m_currentChar = m_pushedChar1;
     57     else
     58         m_currentChar = m_currentString.m_length ? m_currentString.getCurrentChar() : 0;
     59 
     60     m_closed = other.m_closed;
     61     m_empty = other.m_empty;
     62     m_fastPathFlags = other.m_fastPathFlags;
     63     m_numberOfCharactersConsumedPriorToCurrentString = other.m_numberOfCharactersConsumedPriorToCurrentString;
     64     m_numberOfCharactersConsumedPriorToCurrentLine = other.m_numberOfCharactersConsumedPriorToCurrentLine;
     65     m_currentLine = other.m_currentLine;
     66 
     67     m_advanceFunc = other.m_advanceFunc;
     68     m_advanceAndUpdateLineNumberFunc = other.m_advanceAndUpdateLineNumberFunc;
     69 
     70     return *this;
     71 }
     72 
     73 unsigned SegmentedString::length() const
     74 {
     75     unsigned length = m_currentString.m_length;
     76     if (m_pushedChar1) {
     77         ++length;
     78         if (m_pushedChar2)
     79             ++length;
     80     }
     81     if (isComposite()) {
     82         Deque<SegmentedSubstring>::const_iterator it = m_substrings.begin();
     83         Deque<SegmentedSubstring>::const_iterator e = m_substrings.end();
     84         for (; it != e; ++it)
     85             length += it->m_length;
     86     }
     87     return length;
     88 }
     89 
     90 void SegmentedString::setExcludeLineNumbers()
     91 {
     92     m_currentString.setExcludeLineNumbers();
     93     if (isComposite()) {
     94         Deque<SegmentedSubstring>::iterator it = m_substrings.begin();
     95         Deque<SegmentedSubstring>::iterator e = m_substrings.end();
     96         for (; it != e; ++it)
     97             it->setExcludeLineNumbers();
     98     }
     99 }
    100 
    101 void SegmentedString::clear()
    102 {
    103     m_pushedChar1 = 0;
    104     m_pushedChar2 = 0;
    105     m_currentChar = 0;
    106     m_currentString.clear();
    107     m_numberOfCharactersConsumedPriorToCurrentString = 0;
    108     m_numberOfCharactersConsumedPriorToCurrentLine = 0;
    109     m_currentLine = 0;
    110     m_substrings.clear();
    111     m_closed = false;
    112     m_empty = true;
    113     m_fastPathFlags = NoFastPath;
    114     m_advanceFunc = &SegmentedString::advanceEmpty;
    115     m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceEmpty;
    116 }
    117 
    118 void SegmentedString::append(const SegmentedSubstring& s)
    119 {
    120     ASSERT(!m_closed);
    121     if (!s.m_length)
    122         return;
    123 
    124     if (!m_currentString.m_length) {
    125         m_numberOfCharactersConsumedPriorToCurrentString += m_currentString.numberOfCharactersConsumed();
    126         m_currentString = s;
    127         updateAdvanceFunctionPointers();
    128     } else
    129         m_substrings.append(s);
    130     m_empty = false;
    131 }
    132 
    133 void SegmentedString::prepend(const SegmentedSubstring& s)
    134 {
    135     ASSERT(!escaped());
    136     ASSERT(!s.numberOfCharactersConsumed());
    137     if (!s.m_length)
    138         return;
    139 
    140     // FIXME: We're assuming that the prepend were originally consumed by
    141     //        this SegmentedString.  We're also ASSERTing that s is a fresh
    142     //        SegmentedSubstring.  These assumptions are sufficient for our
    143     //        current use, but we might need to handle the more elaborate
    144     //        cases in the future.
    145     m_numberOfCharactersConsumedPriorToCurrentString += m_currentString.numberOfCharactersConsumed();
    146     m_numberOfCharactersConsumedPriorToCurrentString -= s.m_length;
    147     if (!m_currentString.m_length) {
    148         m_currentString = s;
    149         updateAdvanceFunctionPointers();
    150     } else {
    151         // Shift our m_currentString into our list.
    152         m_substrings.prepend(m_currentString);
    153         m_currentString = s;
    154         updateAdvanceFunctionPointers();
    155     }
    156     m_empty = false;
    157 }
    158 
    159 void SegmentedString::close()
    160 {
    161     // Closing a stream twice is likely a coding mistake.
    162     ASSERT(!m_closed);
    163     m_closed = true;
    164 }
    165 
    166 void SegmentedString::append(const SegmentedString& s)
    167 {
    168     ASSERT(!m_closed);
    169     ASSERT(!s.escaped());
    170     append(s.m_currentString);
    171     if (s.isComposite()) {
    172         Deque<SegmentedSubstring>::const_iterator it = s.m_substrings.begin();
    173         Deque<SegmentedSubstring>::const_iterator e = s.m_substrings.end();
    174         for (; it != e; ++it)
    175             append(*it);
    176     }
    177     m_currentChar = m_pushedChar1 ? m_pushedChar1 : (m_currentString.m_length ? m_currentString.getCurrentChar() : 0);
    178 }
    179 
    180 void SegmentedString::prepend(const SegmentedString& s)
    181 {
    182     ASSERT(!escaped());
    183     ASSERT(!s.escaped());
    184     if (s.isComposite()) {
    185         Deque<SegmentedSubstring>::const_reverse_iterator it = s.m_substrings.rbegin();
    186         Deque<SegmentedSubstring>::const_reverse_iterator e = s.m_substrings.rend();
    187         for (; it != e; ++it)
    188             prepend(*it);
    189     }
    190     prepend(s.m_currentString);
    191     m_currentChar = m_pushedChar1 ? m_pushedChar1 : (m_currentString.m_length ? m_currentString.getCurrentChar() : 0);
    192 }
    193 
    194 void SegmentedString::advanceSubstring()
    195 {
    196     if (isComposite()) {
    197         m_numberOfCharactersConsumedPriorToCurrentString += m_currentString.numberOfCharactersConsumed();
    198         m_currentString = m_substrings.takeFirst();
    199         // If we've previously consumed some characters of the non-current
    200         // string, we now account for those characters as part of the current
    201         // string, not as part of "prior to current string."
    202         m_numberOfCharactersConsumedPriorToCurrentString -= m_currentString.numberOfCharactersConsumed();
    203         updateAdvanceFunctionPointers();
    204     } else {
    205         m_currentString.clear();
    206         m_empty = true;
    207         m_fastPathFlags = NoFastPath;
    208         m_advanceFunc = &SegmentedString::advanceEmpty;
    209         m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceEmpty;
    210     }
    211 }
    212 
    213 String SegmentedString::toString() const
    214 {
    215     StringBuilder result;
    216     if (m_pushedChar1) {
    217         result.append(m_pushedChar1);
    218         if (m_pushedChar2)
    219             result.append(m_pushedChar2);
    220     }
    221     m_currentString.appendTo(result);
    222     if (isComposite()) {
    223         Deque<SegmentedSubstring>::const_iterator it = m_substrings.begin();
    224         Deque<SegmentedSubstring>::const_iterator e = m_substrings.end();
    225         for (; it != e; ++it)
    226             it->appendTo(result);
    227     }
    228     return result.toString();
    229 }
    230 
    231 void SegmentedString::advance(unsigned count, UChar* consumedCharacters)
    232 {
    233     ASSERT_WITH_SECURITY_IMPLICATION(count <= length());
    234     for (unsigned i = 0; i < count; ++i) {
    235         consumedCharacters[i] = currentChar();
    236         advance();
    237     }
    238 }
    239 
    240 void SegmentedString::advance8()
    241 {
    242     ASSERT(!m_pushedChar1);
    243     decrementAndCheckLength();
    244     m_currentChar = m_currentString.incrementAndGetCurrentChar8();
    245 }
    246 
    247 void SegmentedString::advance16()
    248 {
    249     ASSERT(!m_pushedChar1);
    250     decrementAndCheckLength();
    251     m_currentChar = m_currentString.incrementAndGetCurrentChar16();
    252 }
    253 
    254 void SegmentedString::advanceAndUpdateLineNumber8()
    255 {
    256     ASSERT(!m_pushedChar1);
    257     ASSERT(m_currentString.getCurrentChar() == m_currentChar);
    258     if (m_currentChar == '\n') {
    259         ++m_currentLine;
    260         m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1;
    261     }
    262     decrementAndCheckLength();
    263     m_currentChar = m_currentString.incrementAndGetCurrentChar8();
    264 }
    265 
    266 void SegmentedString::advanceAndUpdateLineNumber16()
    267 {
    268     ASSERT(!m_pushedChar1);
    269     ASSERT(m_currentString.getCurrentChar() == m_currentChar);
    270     if (m_currentChar == '\n') {
    271         ++m_currentLine;
    272         m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1;
    273     }
    274     decrementAndCheckLength();
    275     m_currentChar = m_currentString.incrementAndGetCurrentChar16();
    276 }
    277 
    278 void SegmentedString::advanceSlowCase()
    279 {
    280     if (m_pushedChar1) {
    281         m_pushedChar1 = m_pushedChar2;
    282         m_pushedChar2 = 0;
    283 
    284         if (m_pushedChar1) {
    285             m_currentChar = m_pushedChar1;
    286             return;
    287         }
    288 
    289         updateAdvanceFunctionPointers();
    290     } else if (m_currentString.m_length) {
    291         if (--m_currentString.m_length == 0)
    292             advanceSubstring();
    293     } else if (!isComposite()) {
    294         m_currentString.clear();
    295         m_empty = true;
    296         m_fastPathFlags = NoFastPath;
    297         m_advanceFunc = &SegmentedString::advanceEmpty;
    298         m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceEmpty;
    299     }
    300     m_currentChar = m_currentString.m_length ? m_currentString.getCurrentChar() : 0;
    301 }
    302 
    303 void SegmentedString::advanceAndUpdateLineNumberSlowCase()
    304 {
    305     if (m_pushedChar1) {
    306         m_pushedChar1 = m_pushedChar2;
    307         m_pushedChar2 = 0;
    308 
    309         if (m_pushedChar1) {
    310             m_currentChar = m_pushedChar1;
    311             return;
    312         }
    313 
    314         updateAdvanceFunctionPointers();
    315     } else if (m_currentString.m_length) {
    316         if (m_currentString.getCurrentChar() == '\n' && m_currentString.doNotExcludeLineNumbers()) {
    317             ++m_currentLine;
    318             // Plus 1 because numberOfCharactersConsumed value hasn't incremented yet; it does with m_length decrement below.
    319             m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1;
    320         }
    321         if (--m_currentString.m_length == 0)
    322             advanceSubstring();
    323         else
    324             m_currentString.incrementAndGetCurrentChar(); // Only need the ++
    325     } else if (!isComposite()) {
    326         m_currentString.clear();
    327         m_empty = true;
    328         m_fastPathFlags = NoFastPath;
    329         m_advanceFunc = &SegmentedString::advanceEmpty;
    330         m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceEmpty;
    331     }
    332 
    333     m_currentChar = m_currentString.m_length ? m_currentString.getCurrentChar() : 0;
    334 }
    335 
    336 void SegmentedString::advanceEmpty()
    337 {
    338     ASSERT(!m_currentString.m_length && !isComposite());
    339     m_currentChar = 0;
    340 }
    341 
    342 void SegmentedString::updateSlowCaseFunctionPointers()
    343 {
    344     m_fastPathFlags = NoFastPath;
    345     m_advanceFunc = &SegmentedString::advanceSlowCase;
    346     m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceAndUpdateLineNumberSlowCase;
    347 }
    348 
    349 OrdinalNumber SegmentedString::currentLine() const
    350 {
    351     return OrdinalNumber::fromZeroBasedInt(m_currentLine);
    352 }
    353 
    354 OrdinalNumber SegmentedString::currentColumn() const
    355 {
    356     int zeroBasedColumn = numberOfCharactersConsumed() - m_numberOfCharactersConsumedPriorToCurrentLine;
    357     return OrdinalNumber::fromZeroBasedInt(zeroBasedColumn);
    358 }
    359 
    360 void SegmentedString::setCurrentPosition(OrdinalNumber line, OrdinalNumber columnAftreProlog, int prologLength)
    361 {
    362     m_currentLine = line.zeroBasedInt();
    363     m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + prologLength - columnAftreProlog.zeroBasedInt();
    364 }
    365 
    366 }
    367