Unreviewed, rolling out r215608.
[WebKit-https.git] / Source / WebCore / platform / SharedBufferChunkReader.cpp
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 "SharedBufferChunkReader.h"
33
34 #include "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.appendVector(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 }