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 "platform/SharedBufferChunkReader.h"
33
34 #include "platform/SharedBuffer.h"
35
36 namespace blink {
37
SharedBufferChunkReader(SharedBuffer * buffer,const Vector<char> & separator)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
SharedBufferChunkReader(SharedBuffer * buffer,const char * separator)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
setSeparator(const Vector<char> & separator)62 void SharedBufferChunkReader::setSeparator(const Vector<char>& separator)
63 {
64 m_separator = separator;
65 }
66
setSeparator(const char * separator)67 void SharedBufferChunkReader::setSeparator(const char* separator)
68 {
69 m_separator.clear();
70 m_separator.append(separator, strlen(separator));
71 }
72
nextChunk(Vector<char> & chunk,bool includeSeparator)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
nextChunkAsUTF8StringWithLatin1Fallback(bool includeSeparator)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
peek(Vector<char> & data,size_t requestedSize)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