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