xref: /AOO41X/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