Home | History | Annotate | Download | only in platform
      1 /*
      2  * Copyright (C) 2011 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "core/platform/SharedBufferChunkReader.h"
     33 
     34 #include "core/platform/SharedBuffer.h"
     35 
     36 namespace WebCore {
     37 
     38 SharedBufferChunkReader::SharedBufferChunkReader(SharedBuffer* buffer, const Vector<char>& separator)
     39     : m_buffer(buffer)
     40     , m_bufferPosition(0)
     41     , m_segment(0)
     42     , m_segmentLength(0)
     43     , m_segmentIndex(0)
     44     , m_reachedEndOfFile(false)
     45     , m_separator(separator)
     46     , m_separatorIndex(0)
     47 {
     48 }
     49 
     50 SharedBufferChunkReader::SharedBufferChunkReader(SharedBuffer* buffer, const char* separator)
     51     : m_buffer(buffer)
     52     , m_bufferPosition(0)
     53     , m_segment(0)
     54     , m_segmentLength(0)
     55     , m_segmentIndex(0)
     56     , m_reachedEndOfFile(false)
     57     , m_separatorIndex(0)
     58 {
     59     setSeparator(separator);
     60 }
     61 
     62 void SharedBufferChunkReader::setSeparator(const Vector<char>& separator)
     63 {
     64     m_separator = separator;
     65 }
     66 
     67 void SharedBufferChunkReader::setSeparator(const char* separator)
     68 {
     69     m_separator.clear();
     70     m_separator.append(separator, strlen(separator));
     71 }
     72 
     73 bool SharedBufferChunkReader::nextChunk(Vector<char>& chunk, bool includeSeparator)
     74 {
     75     if (m_reachedEndOfFile)
     76         return false;
     77 
     78     chunk.clear();
     79     while (true) {
     80         while (m_segmentIndex < m_segmentLength) {
     81             char currentCharacter = m_segment[m_segmentIndex++];
     82             if (currentCharacter != m_separator[m_separatorIndex]) {
     83                 if (m_separatorIndex > 0) {
     84                     ASSERT_WITH_SECURITY_IMPLICATION(m_separatorIndex <= m_separator.size());
     85                     chunk.append(m_separator.data(), m_separatorIndex);
     86                     m_separatorIndex = 0;
     87                 }
     88                 chunk.append(currentCharacter);
     89                 continue;
     90             }
     91             m_separatorIndex++;
     92             if (m_separatorIndex == m_separator.size()) {
     93                 if (includeSeparator)
     94                     chunk.append(m_separator);
     95                 m_separatorIndex = 0;
     96                 return true;
     97             }
     98         }
     99 
    100         // Read the next segment.
    101         m_segmentIndex = 0;
    102         m_bufferPosition += m_segmentLength;
    103         m_segmentLength = m_buffer->getSomeData(m_segment, m_bufferPosition);
    104         if (!m_segmentLength) {
    105             m_reachedEndOfFile = true;
    106             if (m_separatorIndex > 0)
    107                 chunk.append(m_separator.data(), m_separatorIndex);
    108             return !chunk.isEmpty();
    109         }
    110     }
    111     ASSERT_NOT_REACHED();
    112     return false;
    113 }
    114 
    115 String SharedBufferChunkReader::nextChunkAsUTF8StringWithLatin1Fallback(bool includeSeparator)
    116 {
    117     Vector<char> data;
    118     if (!nextChunk(data, includeSeparator))
    119         return String();
    120 
    121     return data.size() ? String::fromUTF8WithLatin1Fallback(data.data(), data.size()) : emptyString();
    122 }
    123 
    124 size_t SharedBufferChunkReader::peek(Vector<char>& data, size_t requestedSize)
    125 {
    126     data.clear();
    127     if (requestedSize <= m_segmentLength - m_segmentIndex) {
    128         data.append(m_segment + m_segmentIndex, requestedSize);
    129         return requestedSize;
    130     }
    131 
    132     size_t readBytesCount = m_segmentLength - m_segmentIndex;
    133     data.append(m_segment + m_segmentIndex, readBytesCount);
    134 
    135     size_t bufferPosition = m_bufferPosition + m_segmentLength;
    136     const char* segment = 0;
    137     while (size_t segmentLength = m_buffer->getSomeData(segment, bufferPosition)) {
    138         if (requestedSize <= readBytesCount + segmentLength) {
    139             data.append(segment, requestedSize - readBytesCount);
    140             readBytesCount += (requestedSize - readBytesCount);
    141             break;
    142         }
    143         data.append(segment, segmentLength);
    144         readBytesCount += segmentLength;
    145         bufferPosition += segmentLength;
    146     }
    147     return readBytesCount;
    148 }
    149 
    150 }
    151