xref: /AOO41X/main/io/source/stm/streamhelper.cxx (revision 3716f815df2d68347af345f8524e39097ef453f6)
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