xref: /trunk/main/io/source/stm/streamhelper.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_io.hxx"
30 #include <rtl/alloc.h>
31 
32 #include <limits>
33 #include <string.h>
34 
35 #include <com/sun/star/uno/Sequence.hxx>
36 
37 #include <com/sun/star/uno/Exception.hpp>
38 
39 using namespace ::com::sun::star::uno;
40 
41 #include "streamhelper.hxx"
42 
43 namespace io_stm {
44 
45 void MemFIFO::write( const Sequence< sal_Int8 > &seq )
46     throw ( IFIFO_OutOfMemoryException,
47             IFIFO_OutOfBoundsException )
48 {
49     try
50     {
51         writeAt(getSize(), seq );
52     }
53     catch( IRingBuffer_OutOfMemoryException & )
54     {
55         throw IFIFO_OutOfMemoryException();
56     }
57     catch( IRingBuffer_OutOfBoundsException & )
58     {
59         throw IFIFO_OutOfBoundsException();
60     }
61 }
62 
63 void MemFIFO::read( Sequence<sal_Int8> &seq , sal_Int32 nBufferLen ) throw (IFIFO_OutOfBoundsException)
64 {
65     try
66     {
67         readAt(0, seq , nBufferLen);
68         forgetFromStart( nBufferLen );
69     }
70     catch ( IRingBuffer_OutOfBoundsException & )
71     {
72         throw IFIFO_OutOfBoundsException();
73     }
74 }
75 
76 void MemFIFO::skip( sal_Int32 nBytesToSkip ) throw ( IFIFO_OutOfBoundsException )
77 {
78     try
79     {
80         forgetFromStart( nBytesToSkip );
81     }
82     catch( IRingBuffer_OutOfBoundsException & )
83     {
84         throw IFIFO_OutOfBoundsException();
85     }
86 }
87 
88 
89 
90 MemRingBuffer::MemRingBuffer()
91 {
92     m_nBufferLen            = 0;
93     m_p                     = 0;
94     m_nStart                = 0;
95     m_nOccupiedBuffer       = 0;
96 }
97 
98 MemRingBuffer::~MemRingBuffer()
99 {
100     if( m_p ) {
101         rtl_freeMemory( m_p );
102     }
103 }
104 
105 void MemRingBuffer::resizeBuffer( sal_Int32 nMinSize ) throw( IRingBuffer_OutOfMemoryException)
106 {
107     sal_Int32 nNewLen = 1;
108 
109     while( nMinSize > nNewLen ) {
110         nNewLen = nNewLen << 1;
111     }
112 
113     // buffer never shrinks !
114     if( nNewLen < m_nBufferLen ) {
115         nNewLen = m_nBufferLen;
116     }
117 
118     if( nNewLen != m_nBufferLen ) {
119         m_p = ( sal_Int8 * ) rtl_reallocateMemory( m_p , nNewLen );
120         if( !m_p ) {
121             throw IRingBuffer_OutOfMemoryException();
122         }
123 
124         if( m_nStart + m_nOccupiedBuffer > m_nBufferLen ) {
125             memmove( &( m_p[m_nStart+(nNewLen-m_nBufferLen)]) , &(m_p[m_nStart]) , m_nBufferLen - m_nStart );
126             m_nStart += nNewLen - m_nBufferLen;
127         }
128         m_nBufferLen = nNewLen;
129     }
130 }
131 
132 
133 void MemRingBuffer::readAt( sal_Int32 nPos, Sequence<sal_Int8> &seq , sal_Int32 nBytesToRead ) const
134                                                         throw(IRingBuffer_OutOfBoundsException)
135 {
136     if( nPos + nBytesToRead > m_nOccupiedBuffer ) {
137         throw IRingBuffer_OutOfBoundsException();
138     }
139 
140     sal_Int32 nStartReadingPos = nPos + m_nStart;
141     if( nStartReadingPos >= m_nBufferLen ) {
142         nStartReadingPos -= m_nBufferLen;
143     }
144 
145     seq.realloc( nBytesToRead );
146 
147     if( nStartReadingPos + nBytesToRead > m_nBufferLen ) {
148         sal_Int32 nDeltaLen = m_nBufferLen - nStartReadingPos;
149         memcpy( seq.getArray() , &(m_p[nStartReadingPos]) , nDeltaLen );
150         memcpy( &(seq.getArray()[nDeltaLen]), m_p , nBytesToRead - nDeltaLen );
151     }
152     else {
153         memcpy( seq.getArray() , &(m_p[nStartReadingPos]) , nBytesToRead );
154     }
155 }
156 
157 
158 void MemRingBuffer::writeAt( sal_Int32 nPos, const Sequence<sal_Int8> &seq )
159                                                         throw (IRingBuffer_OutOfBoundsException,
160                                                                 IRingBuffer_OutOfMemoryException )
161 {
162     checkInvariants();
163     sal_Int32 nLen = seq.getLength();
164 
165     if( nPos < 0 || nPos > std::numeric_limits< sal_Int32 >::max() - nLen )
166     {
167         throw IRingBuffer_OutOfBoundsException();
168     }
169 
170     if( nPos + nLen - m_nOccupiedBuffer > 0 ) {
171         resizeBuffer( nPos + seq.getLength() );
172     }
173 
174     sal_Int32 nStartWritingIndex = m_nStart + nPos;
175     if( nStartWritingIndex >= m_nBufferLen ) {
176         nStartWritingIndex -= m_nBufferLen;
177     }
178 
179     if( nLen + nStartWritingIndex > m_nBufferLen ) {
180         // two area copy
181         memcpy( &(m_p[nStartWritingIndex]) , seq.getConstArray(), m_nBufferLen-nStartWritingIndex );
182         memcpy( m_p , &( seq.getConstArray()[m_nBufferLen-nStartWritingIndex] ),
183                                         nLen - (m_nBufferLen-nStartWritingIndex) );
184 
185     }
186     else {
187         // one area copy
188         memcpy( &( m_p[nStartWritingIndex]), seq.getConstArray() , nLen );
189     }
190     m_nOccupiedBuffer = Max( nPos + seq.getLength() , m_nOccupiedBuffer );
191     checkInvariants();
192 }
193 
194 
195 sal_Int32 MemRingBuffer::getSize()  const throw()
196 {
197     return m_nOccupiedBuffer;
198 }
199 
200 void MemRingBuffer::forgetFromStart( sal_Int32 nBytesToForget ) throw (IRingBuffer_OutOfBoundsException)
201 {
202     checkInvariants();
203     if( nBytesToForget > m_nOccupiedBuffer ) {
204         throw IRingBuffer_OutOfBoundsException();
205     }
206     m_nStart += nBytesToForget;
207     if( m_nStart >= m_nBufferLen ) {
208         m_nStart = m_nStart - m_nBufferLen;
209     }
210     m_nOccupiedBuffer -= nBytesToForget;
211     checkInvariants();
212 }
213 
214 
215 void MemRingBuffer::forgetFromEnd( sal_Int32 nBytesToForget ) throw (IRingBuffer_OutOfBoundsException)
216 {
217     checkInvariants();
218     if( nBytesToForget > m_nOccupiedBuffer ) {
219         throw IRingBuffer_OutOfBoundsException();
220     }
221     m_nOccupiedBuffer -= nBytesToForget;
222     checkInvariants();
223 }
224 
225 
226 void MemRingBuffer::shrink() throw ()
227 {
228     checkInvariants();
229 
230     // Up to now, only shrinking of while buffer works.
231     // No other shrinking supported up to now.
232     if( ! m_nOccupiedBuffer ) {
233         if( m_p ) {
234             free( m_p );
235         }
236         m_p = 0;
237         m_nBufferLen = 0;
238         m_nStart = 0;
239     }
240 
241     checkInvariants();
242 }
243 
244 }
245