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 
25 // MARKER(update_precomp.py): autogen include statement, do not remove
26 #include "precompiled_xmlhelp.hxx"
27 #include <rtl/memory.h>
28 #include "bufferedinputstream.hxx"
29 
30 
31 using namespace cppu;
32 using namespace com::sun::star::uno;
33 using namespace com::sun::star::lang;
34 using namespace com::sun::star::io;
35 using namespace chelp;
36 
37 
turnToSeekable(const Reference<XInputStream> & xInputStream)38 Reference<XInputStream> chelp::turnToSeekable(const Reference<XInputStream>& xInputStream)
39 {
40 	if( ! xInputStream.is() )
41 		return xInputStream;
42 
43 	Reference<XSeekable> xSeekable(xInputStream,UNO_QUERY);
44 
45 	if( xSeekable.is() )
46 		return xInputStream;
47 
48 	return new BufferedInputStream(xInputStream);
49 }
50 
51 
52 
BufferedInputStream(const Reference<XInputStream> & xInputStream)53 BufferedInputStream::BufferedInputStream(const Reference<XInputStream>& xInputStream)
54 	: m_nBufferLocation(0),
55 	  m_nBufferSize(0),
56 	  m_pBuffer(new sal_Int8[1]) // Initialize with one to avoid gcc compiler warnings
57 {
58 	try
59 	{
60 		sal_Int32 num;
61 		sal_Int8  *tmp;
62 		Sequence< sal_Int8 > aData(4096);
63 		do{
64 			num = xInputStream->readBytes(aData,4096);
65 			if( num > 0 )
66 			{
67 				tmp = m_pBuffer;
68 				m_pBuffer = new sal_Int8[m_nBufferSize+num];
69 				rtl_copyMemory((void *)(m_pBuffer),
70 							   (void *)(tmp),
71 							   sal_uInt32(m_nBufferSize));
72 				rtl_copyMemory((void *)(m_pBuffer+m_nBufferSize),
73 							   (void *)(aData.getArray()),
74 							   sal_uInt32(num));
75 				m_nBufferSize += num;
76 				delete[] tmp;
77 			}
78 		} while( num == 4096 );
79 	}
80 	catch( const NotConnectedException&)
81 	{
82 	}
83 	catch( const BufferSizeExceededException&)
84 	{
85 	}
86 	catch( const IOException&)
87 	{
88 	}
89 	catch( const RuntimeException&)
90 	{
91 	}
92 	xInputStream->closeInput();
93 }
94 
95 
~BufferedInputStream()96 BufferedInputStream::~BufferedInputStream()
97 {
98 	delete[] m_pBuffer;
99 }
100 
101 
queryInterface(const Type & rType)102 Any SAL_CALL BufferedInputStream::queryInterface( const Type& rType ) throw( RuntimeException )
103 {
104 	Any aRet = ::cppu::queryInterface( rType,
105 									   SAL_STATIC_CAST( XInputStream*,this ),
106 									   SAL_STATIC_CAST( XSeekable*,this ) );
107 
108 	return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
109 }
110 
111 
acquire(void)112 void SAL_CALL BufferedInputStream::acquire( void ) throw()
113 {
114 	OWeakObject::acquire();
115 }
116 
117 
release(void)118 void SAL_CALL BufferedInputStream::release( void ) throw()
119 {
120 	OWeakObject::release();
121 }
122 
123 
124 
readBytes(Sequence<sal_Int8> & aData,sal_Int32 nBytesToRead)125 sal_Int32 SAL_CALL BufferedInputStream::readBytes( Sequence< sal_Int8 >& aData,sal_Int32 nBytesToRead )
126 	throw( NotConnectedException,
127 		   BufferSizeExceededException,
128 		   IOException,
129 		   RuntimeException)
130 {
131 	osl::MutexGuard aGuard( m_aMutex );
132 
133 	if( 0 > nBytesToRead )
134 		throw BufferSizeExceededException();
135 
136 	if( m_nBufferLocation + nBytesToRead > m_nBufferSize )
137 		nBytesToRead = m_nBufferSize - m_nBufferLocation;
138 
139 	if( aData.getLength() < nBytesToRead )
140 		aData.realloc(nBytesToRead);
141 
142 	rtl_copyMemory((void*)(aData.getArray()),
143 				   (void*)(m_pBuffer+m_nBufferLocation),
144 				   nBytesToRead);
145 
146 	return nBytesToRead;
147 }
148 
149 
readSomeBytes(Sequence<sal_Int8> & aData,sal_Int32 nMaxBytesToRead)150 sal_Int32 SAL_CALL BufferedInputStream::readSomeBytes(
151 	Sequence< sal_Int8 >& aData,sal_Int32 nMaxBytesToRead )
152 	throw( NotConnectedException,
153 		   BufferSizeExceededException,
154 		   IOException,
155 		   RuntimeException)
156 {
157 	return readBytes(aData,nMaxBytesToRead);
158 }
159 
160 
161 
skipBytes(sal_Int32 nBytesToSkip)162 void SAL_CALL BufferedInputStream::skipBytes( sal_Int32 nBytesToSkip )
163 	throw( NotConnectedException,
164 		   BufferSizeExceededException,
165 		   IOException,
166 		   RuntimeException )
167 {
168 	try
169 	{
170 		seek(m_nBufferLocation+nBytesToSkip);
171 	}
172 	catch( const IllegalArgumentException& )
173 	{
174 		throw BufferSizeExceededException();
175 	}
176 }
177 
178 
179 
available(void)180 sal_Int32 SAL_CALL BufferedInputStream::available( void )
181 	throw( NotConnectedException,
182 		   IOException,
183 		   RuntimeException )
184 {
185 	osl::MutexGuard aGuard( m_aMutex );
186 	return  m_nBufferSize-m_nBufferLocation;
187 }
188 
189 
190 
closeInput(void)191 void SAL_CALL BufferedInputStream::closeInput( void )
192 	throw( NotConnectedException,
193 		   IOException,
194 		   RuntimeException )
195 {
196 }
197 
198 
seek(sal_Int64 location)199 void SAL_CALL BufferedInputStream::seek( sal_Int64 location )
200 	throw( IllegalArgumentException,
201 		   IOException,
202 		   RuntimeException )
203 {
204 	if( 0 <= location && location < m_nBufferSize )
205 	{
206 		osl::MutexGuard aGuard( m_aMutex );
207 		m_nBufferLocation = sal::static_int_cast<sal_Int32>( location );
208 	}
209 	else
210 		throw IllegalArgumentException();
211 }
212 
213 
214 
getPosition(void)215 sal_Int64 SAL_CALL BufferedInputStream::getPosition( void )
216 	throw( IOException,
217 		   RuntimeException )
218 {
219 	osl::MutexGuard aGuard( m_aMutex );
220 	return m_nBufferLocation;
221 }
222 
223 
224 
getLength(void)225 sal_Int64 SAL_CALL BufferedInputStream::getLength( void ) throw( IOException,RuntimeException )
226 {
227 	osl::MutexGuard aGuard( m_aMutex );
228 	return m_nBufferSize;
229 }
230