xref: /trunk/main/io/source/stm/streamhelper.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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 {
43     try
44     {
45         writeAt(getSize(), seq );
46     }
47     catch( IRingBuffer_OutOfMemoryException & )
48     {
49         throw IFIFO_OutOfMemoryException();
50     }
51     catch( IRingBuffer_OutOfBoundsException & )
52     {
53         throw IFIFO_OutOfBoundsException();
54     }
55 }
56 
read(Sequence<sal_Int8> & seq,sal_Int32 nBufferLen)57 void MemFIFO::read( Sequence<sal_Int8> &seq , sal_Int32 nBufferLen )
58 {
59     try
60     {
61         readAt(0, seq , nBufferLen);
62         forgetFromStart( nBufferLen );
63     }
64     catch ( IRingBuffer_OutOfBoundsException & )
65     {
66         throw IFIFO_OutOfBoundsException();
67     }
68 }
69 
skip(sal_Int32 nBytesToSkip)70 void MemFIFO::skip( sal_Int32 nBytesToSkip )
71 {
72     try
73     {
74         forgetFromStart( nBytesToSkip );
75     }
76     catch( IRingBuffer_OutOfBoundsException & )
77     {
78         throw IFIFO_OutOfBoundsException();
79     }
80 }
81 
82 
83 
MemRingBuffer()84 MemRingBuffer::MemRingBuffer()
85 {
86     m_nBufferLen            = 0;
87     m_p                     = 0;
88     m_nStart                = 0;
89     m_nOccupiedBuffer       = 0;
90 }
91 
~MemRingBuffer()92 MemRingBuffer::~MemRingBuffer()
93 {
94     if( m_p ) {
95         rtl_freeMemory( m_p );
96     }
97 }
98 
resizeBuffer(sal_Int32 nMinSize)99 void MemRingBuffer::resizeBuffer( sal_Int32 nMinSize )
100 {
101     sal_Int32 nNewLen = 1;
102 
103     while( nMinSize > nNewLen ) {
104         nNewLen = nNewLen << 1;
105     }
106 
107     // buffer never shrinks !
108     if( nNewLen < m_nBufferLen ) {
109         nNewLen = m_nBufferLen;
110     }
111 
112     if( nNewLen != m_nBufferLen ) {
113         m_p = ( sal_Int8 * ) rtl_reallocateMemory( m_p , nNewLen );
114         if( !m_p ) {
115             throw IRingBuffer_OutOfMemoryException();
116         }
117 
118         if( m_nStart + m_nOccupiedBuffer > m_nBufferLen ) {
119             memmove( &( m_p[m_nStart+(nNewLen-m_nBufferLen)]) , &(m_p[m_nStart]) , m_nBufferLen - m_nStart );
120             m_nStart += nNewLen - m_nBufferLen;
121         }
122         m_nBufferLen = nNewLen;
123     }
124 }
125 
126 
readAt(sal_Int32 nPos,Sequence<sal_Int8> & seq,sal_Int32 nBytesToRead) const127 void MemRingBuffer::readAt( sal_Int32 nPos, Sequence<sal_Int8> &seq , sal_Int32 nBytesToRead ) const
128 {
129     if( nPos + nBytesToRead > m_nOccupiedBuffer ) {
130         throw IRingBuffer_OutOfBoundsException();
131     }
132 
133     sal_Int32 nStartReadingPos = nPos + m_nStart;
134     if( nStartReadingPos >= m_nBufferLen ) {
135         nStartReadingPos -= m_nBufferLen;
136     }
137 
138     seq.realloc( nBytesToRead );
139 
140     if( nStartReadingPos + nBytesToRead > m_nBufferLen ) {
141         sal_Int32 nDeltaLen = m_nBufferLen - nStartReadingPos;
142         memcpy( seq.getArray() , &(m_p[nStartReadingPos]) , nDeltaLen );
143         memcpy( &(seq.getArray()[nDeltaLen]), m_p , nBytesToRead - nDeltaLen );
144     }
145     else {
146         memcpy( seq.getArray() , &(m_p[nStartReadingPos]) , nBytesToRead );
147     }
148 }
149 
150 
writeAt(sal_Int32 nPos,const Sequence<sal_Int8> & seq)151 void MemRingBuffer::writeAt( sal_Int32 nPos, const Sequence<sal_Int8> &seq )
152 {
153     checkInvariants();
154     sal_Int32 nLen = seq.getLength();
155 
156     if( nPos < 0 || nPos > std::numeric_limits< sal_Int32 >::max() - nLen )
157     {
158         throw IRingBuffer_OutOfBoundsException();
159     }
160 
161     if( nPos + nLen - m_nOccupiedBuffer > 0 ) {
162         resizeBuffer( nPos + seq.getLength() );
163     }
164 
165     sal_Int32 nStartWritingIndex = m_nStart + nPos;
166     if( nStartWritingIndex >= m_nBufferLen ) {
167         nStartWritingIndex -= m_nBufferLen;
168     }
169 
170     if( nLen + nStartWritingIndex > m_nBufferLen ) {
171         // two area copy
172         memcpy( &(m_p[nStartWritingIndex]) , seq.getConstArray(), m_nBufferLen-nStartWritingIndex );
173         memcpy( m_p , &( seq.getConstArray()[m_nBufferLen-nStartWritingIndex] ),
174                                         nLen - (m_nBufferLen-nStartWritingIndex) );
175 
176     }
177     else {
178         // one area copy
179         memcpy( &( m_p[nStartWritingIndex]), seq.getConstArray() , nLen );
180     }
181     m_nOccupiedBuffer = Max( nPos + seq.getLength() , m_nOccupiedBuffer );
182     checkInvariants();
183 }
184 
185 
getSize() const186 sal_Int32 MemRingBuffer::getSize()  const throw()
187 {
188     return m_nOccupiedBuffer;
189 }
190 
forgetFromStart(sal_Int32 nBytesToForget)191 void MemRingBuffer::forgetFromStart( sal_Int32 nBytesToForget )
192 {
193     checkInvariants();
194     if( nBytesToForget > m_nOccupiedBuffer ) {
195         throw IRingBuffer_OutOfBoundsException();
196     }
197     m_nStart += nBytesToForget;
198     if( m_nStart >= m_nBufferLen ) {
199         m_nStart = m_nStart - m_nBufferLen;
200     }
201     m_nOccupiedBuffer -= nBytesToForget;
202     checkInvariants();
203 }
204 
205 
forgetFromEnd(sal_Int32 nBytesToForget)206 void MemRingBuffer::forgetFromEnd( sal_Int32 nBytesToForget )
207 {
208     checkInvariants();
209     if( nBytesToForget > m_nOccupiedBuffer ) {
210         throw IRingBuffer_OutOfBoundsException();
211     }
212     m_nOccupiedBuffer -= nBytesToForget;
213     checkInvariants();
214 }
215 
216 
shrink()217 void MemRingBuffer::shrink() throw ()
218 {
219     checkInvariants();
220 
221     // Up to now, only shrinking of while buffer works.
222     // No other shrinking supported up to now.
223     if( ! m_nOccupiedBuffer ) {
224         if( m_p ) {
225             free( m_p );
226         }
227         m_p = 0;
228         m_nBufferLen = 0;
229         m_nStart = 0;
230     }
231 
232     checkInvariants();
233 }
234 
235 }
236