1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_io.hxx"
26 #include <rtl/alloc.h>
27
28 #include <limits>
29 #include <string.h>
30
31 #include <com/sun/star/uno/Sequence.hxx>
32
33 #include <com/sun/star/uno/Exception.hpp>
34
35 using namespace ::com::sun::star::uno;
36
37 #include "streamhelper.hxx"
38
39 namespace io_stm {
40
write(const Sequence<sal_Int8> & seq)41 void MemFIFO::write( const Sequence< sal_Int8 > &seq )
42 throw ( IFIFO_OutOfMemoryException,
43 IFIFO_OutOfBoundsException )
44 {
45 try
46 {
47 writeAt(getSize(), seq );
48 }
49 catch( IRingBuffer_OutOfMemoryException & )
50 {
51 throw IFIFO_OutOfMemoryException();
52 }
53 catch( IRingBuffer_OutOfBoundsException & )
54 {
55 throw IFIFO_OutOfBoundsException();
56 }
57 }
58
read(Sequence<sal_Int8> & seq,sal_Int32 nBufferLen)59 void MemFIFO::read( Sequence<sal_Int8> &seq , sal_Int32 nBufferLen ) throw (IFIFO_OutOfBoundsException)
60 {
61 try
62 {
63 readAt(0, seq , nBufferLen);
64 forgetFromStart( nBufferLen );
65 }
66 catch ( IRingBuffer_OutOfBoundsException & )
67 {
68 throw IFIFO_OutOfBoundsException();
69 }
70 }
71
skip(sal_Int32 nBytesToSkip)72 void MemFIFO::skip( sal_Int32 nBytesToSkip ) throw ( IFIFO_OutOfBoundsException )
73 {
74 try
75 {
76 forgetFromStart( nBytesToSkip );
77 }
78 catch( IRingBuffer_OutOfBoundsException & )
79 {
80 throw IFIFO_OutOfBoundsException();
81 }
82 }
83
84
85
MemRingBuffer()86 MemRingBuffer::MemRingBuffer()
87 {
88 m_nBufferLen = 0;
89 m_p = 0;
90 m_nStart = 0;
91 m_nOccupiedBuffer = 0;
92 }
93
~MemRingBuffer()94 MemRingBuffer::~MemRingBuffer()
95 {
96 if( m_p ) {
97 rtl_freeMemory( m_p );
98 }
99 }
100
resizeBuffer(sal_Int32 nMinSize)101 void MemRingBuffer::resizeBuffer( sal_Int32 nMinSize ) throw( IRingBuffer_OutOfMemoryException)
102 {
103 sal_Int32 nNewLen = 1;
104
105 while( nMinSize > nNewLen ) {
106 nNewLen = nNewLen << 1;
107 }
108
109 // buffer never shrinks !
110 if( nNewLen < m_nBufferLen ) {
111 nNewLen = m_nBufferLen;
112 }
113
114 if( nNewLen != m_nBufferLen ) {
115 m_p = ( sal_Int8 * ) rtl_reallocateMemory( m_p , nNewLen );
116 if( !m_p ) {
117 throw IRingBuffer_OutOfMemoryException();
118 }
119
120 if( m_nStart + m_nOccupiedBuffer > m_nBufferLen ) {
121 memmove( &( m_p[m_nStart+(nNewLen-m_nBufferLen)]) , &(m_p[m_nStart]) , m_nBufferLen - m_nStart );
122 m_nStart += nNewLen - m_nBufferLen;
123 }
124 m_nBufferLen = nNewLen;
125 }
126 }
127
128
readAt(sal_Int32 nPos,Sequence<sal_Int8> & seq,sal_Int32 nBytesToRead) const129 void MemRingBuffer::readAt( sal_Int32 nPos, Sequence<sal_Int8> &seq , sal_Int32 nBytesToRead ) const
130 throw(IRingBuffer_OutOfBoundsException)
131 {
132 if( nPos + nBytesToRead > m_nOccupiedBuffer ) {
133 throw IRingBuffer_OutOfBoundsException();
134 }
135
136 sal_Int32 nStartReadingPos = nPos + m_nStart;
137 if( nStartReadingPos >= m_nBufferLen ) {
138 nStartReadingPos -= m_nBufferLen;
139 }
140
141 seq.realloc( nBytesToRead );
142
143 if( nStartReadingPos + nBytesToRead > m_nBufferLen ) {
144 sal_Int32 nDeltaLen = m_nBufferLen - nStartReadingPos;
145 memcpy( seq.getArray() , &(m_p[nStartReadingPos]) , nDeltaLen );
146 memcpy( &(seq.getArray()[nDeltaLen]), m_p , nBytesToRead - nDeltaLen );
147 }
148 else {
149 memcpy( seq.getArray() , &(m_p[nStartReadingPos]) , nBytesToRead );
150 }
151 }
152
153
writeAt(sal_Int32 nPos,const Sequence<sal_Int8> & seq)154 void MemRingBuffer::writeAt( sal_Int32 nPos, const Sequence<sal_Int8> &seq )
155 throw (IRingBuffer_OutOfBoundsException,
156 IRingBuffer_OutOfMemoryException )
157 {
158 checkInvariants();
159 sal_Int32 nLen = seq.getLength();
160
161 if( nPos < 0 || nPos > std::numeric_limits< sal_Int32 >::max() - nLen )
162 {
163 throw IRingBuffer_OutOfBoundsException();
164 }
165
166 if( nPos + nLen - m_nOccupiedBuffer > 0 ) {
167 resizeBuffer( nPos + seq.getLength() );
168 }
169
170 sal_Int32 nStartWritingIndex = m_nStart + nPos;
171 if( nStartWritingIndex >= m_nBufferLen ) {
172 nStartWritingIndex -= m_nBufferLen;
173 }
174
175 if( nLen + nStartWritingIndex > m_nBufferLen ) {
176 // two area copy
177 memcpy( &(m_p[nStartWritingIndex]) , seq.getConstArray(), m_nBufferLen-nStartWritingIndex );
178 memcpy( m_p , &( seq.getConstArray()[m_nBufferLen-nStartWritingIndex] ),
179 nLen - (m_nBufferLen-nStartWritingIndex) );
180
181 }
182 else {
183 // one area copy
184 memcpy( &( m_p[nStartWritingIndex]), seq.getConstArray() , nLen );
185 }
186 m_nOccupiedBuffer = Max( nPos + seq.getLength() , m_nOccupiedBuffer );
187 checkInvariants();
188 }
189
190
getSize() const191 sal_Int32 MemRingBuffer::getSize() const throw()
192 {
193 return m_nOccupiedBuffer;
194 }
195
forgetFromStart(sal_Int32 nBytesToForget)196 void MemRingBuffer::forgetFromStart( sal_Int32 nBytesToForget ) throw (IRingBuffer_OutOfBoundsException)
197 {
198 checkInvariants();
199 if( nBytesToForget > m_nOccupiedBuffer ) {
200 throw IRingBuffer_OutOfBoundsException();
201 }
202 m_nStart += nBytesToForget;
203 if( m_nStart >= m_nBufferLen ) {
204 m_nStart = m_nStart - m_nBufferLen;
205 }
206 m_nOccupiedBuffer -= nBytesToForget;
207 checkInvariants();
208 }
209
210
forgetFromEnd(sal_Int32 nBytesToForget)211 void MemRingBuffer::forgetFromEnd( sal_Int32 nBytesToForget ) throw (IRingBuffer_OutOfBoundsException)
212 {
213 checkInvariants();
214 if( nBytesToForget > m_nOccupiedBuffer ) {
215 throw IRingBuffer_OutOfBoundsException();
216 }
217 m_nOccupiedBuffer -= nBytesToForget;
218 checkInvariants();
219 }
220
221
shrink()222 void MemRingBuffer::shrink() throw ()
223 {
224 checkInvariants();
225
226 // Up to now, only shrinking of while buffer works.
227 // No other shrinking supported up to now.
228 if( ! m_nOccupiedBuffer ) {
229 if( m_p ) {
230 free( m_p );
231 }
232 m_p = 0;
233 m_nBufferLen = 0;
234 m_nStart = 0;
235 }
236
237 checkInvariants();
238 }
239
240 }
241