151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)/*
251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * Copyright (C) 2013, Opera Software ASA. All rights reserved.
351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) *
451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without
551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * modification, are permitted provided that the following conditions are
651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * met:
751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) *
851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) *     * Redistributions of source code must retain the above copyright
951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * notice, this list of conditions and the following disclaimer.
1051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) *     * Redistributions in binary form must reproduce the above
1151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
1251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * in the documentation and/or other materials provided with the
1351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * distribution.
1451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
1551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * contributors may be used to endorse or promote products derived from
1651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * this software without specific prior written permission.
1751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) *
1851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) */
3051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
3151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "config.h"
325d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/html/track/vtt/BufferedLineReader.h"
3351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
3451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "wtf/unicode/CharacterNames.h"
3551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
36c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
3751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
3851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)bool BufferedLineReader::getLine(String& line)
3951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){
4051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (m_maybeSkipLF) {
4151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // We ran out of data after a CR (U+000D), which means that we may be
4251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // in the middle of a CRLF pair. If the next character is a LF (U+000A)
4351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // then skip it, and then (unconditionally) return the buffered line.
4451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (!m_buffer.isEmpty()) {
4551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            scanCharacter(newlineCharacter);
4651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            m_maybeSkipLF = false;
4751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        }
4851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // If there was no (new) data available, then keep m_maybeSkipLF set,
4951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // and fall through all the way down to the EOS check at the end of
5051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // the method.
5151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
5251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
5351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    bool shouldReturnLine = false;
5451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    bool checkForLF = false;
5551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    while (!m_buffer.isEmpty()) {
5651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        UChar c = m_buffer.currentChar();
5751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        m_buffer.advance();
5851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
5951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (c == newlineCharacter || c == carriageReturn) {
6051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            // We found a line ending. Return the accumulated line.
6151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            shouldReturnLine = true;
6251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            checkForLF = (c == carriageReturn);
6351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            break;
6451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        }
6551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
6651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // NULs are transformed into U+FFFD (REPLACEMENT CHAR.) in step 1 of
6751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // the WebVTT parser algorithm.
6851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (c == '\0')
6951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            c = replacementCharacter;
7051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
7151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        m_lineBuffer.append(c);
7251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
7351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
7451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (checkForLF) {
7551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // May be in the middle of a CRLF pair.
7651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (!m_buffer.isEmpty()) {
7751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            // Scan a potential newline character.
7851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            scanCharacter(newlineCharacter);
7951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        } else {
8051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            // Check for the LF on the next call (unless we reached EOS, in
8151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            // which case we'll return the contents of the line buffer, and
8251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            // reset state for the next line.)
8351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            m_maybeSkipLF = true;
8451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        }
8551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
8651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
8751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (isAtEndOfStream()) {
8851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // We've reached the end of the stream proper. Emit a line if the
8951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // current line buffer is non-empty. (Note that if shouldReturnLine is
9051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // set already, we want to return a line nonetheless.)
9151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        shouldReturnLine |= !m_lineBuffer.isEmpty();
9251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
9351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
9451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (shouldReturnLine) {
9551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        line = m_lineBuffer.toString();
9651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        m_lineBuffer.clear();
9751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return true;
9851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
9951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
10051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    ASSERT(m_buffer.isEmpty());
10151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    return false;
10251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)}
10351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
104c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
105