xref: /AOO41X/main/comphelper/source/streaming/memorystream.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_comphelper.hxx"
30 
31 #include "comphelper_module.hxx"
32 
33 #include <com/sun/star/io/XStream.hpp>
34 #include <com/sun/star/io/XSeekableInputStream.hpp>
35 #include <com/sun/star/io/XTruncate.hpp>
36 #include <com/sun/star/uno/XComponentContext.hpp>
37 #include <cppuhelper/implbase4.hxx>
38 
39 #include <string.h>
40 #include <vector>
41 
42 using ::rtl::OUString;
43 using ::cppu::OWeakObject;
44 using ::cppu::WeakImplHelper4;
45 using namespace ::com::sun::star::io;
46 using namespace ::com::sun::star::uno;
47 using namespace ::com::sun::star::lang;
48 using namespace ::osl;
49 
50 namespace comphelper
51 {
52 
53 class UNOMemoryStream : public WeakImplHelper4 < XStream, XSeekableInputStream, XOutputStream, XTruncate >
54 {
55 public:
56 	UNOMemoryStream();
57 	virtual ~UNOMemoryStream();
58 
59 	// XStream
60     virtual Reference< XInputStream > SAL_CALL getInputStream(  ) throw (RuntimeException);
61     virtual Reference< XOutputStream > SAL_CALL getOutputStream(  ) throw (RuntimeException);
62 
63     // XInputStream
64     virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException);
65     virtual sal_Int32 SAL_CALL readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException);
66     virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException);
67     virtual sal_Int32 SAL_CALL available() throw (NotConnectedException, IOException, RuntimeException);
68     virtual void SAL_CALL closeInput() throw (NotConnectedException, IOException, RuntimeException);
69 
70     // XSeekable
71     virtual void SAL_CALL seek( sal_Int64 location ) throw (IllegalArgumentException, IOException, RuntimeException);
72     virtual sal_Int64 SAL_CALL getPosition() throw (IOException, RuntimeException);
73     virtual sal_Int64 SAL_CALL getLength() throw (IOException, RuntimeException);
74 
75     // XOutputStream
76     virtual void SAL_CALL writeBytes( const Sequence< sal_Int8 >& aData ) throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException);
77     virtual void SAL_CALL flush() throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException);
78     virtual void SAL_CALL closeOutput() throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException);
79 
80     // XTruncate
81     virtual void SAL_CALL truncate() throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
82 
83     // XServiceInfo - static versions (used for component registration)
84     static ::rtl::OUString SAL_CALL getImplementationName_static();
85     static Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_static();
86     static Reference< XInterface > SAL_CALL Create( const Reference< ::com::sun::star::uno::XComponentContext >& );
87 
88 private:
89 	std::vector< sal_Int8 > maData;
90 	sal_Int32 mnCursor;
91 };
92 
93 UNOMemoryStream::UNOMemoryStream()
94 : mnCursor(0)
95 {
96 }
97 
98 UNOMemoryStream::~UNOMemoryStream()
99 {
100 }
101 
102 // XStream
103 Reference< XInputStream > SAL_CALL UNOMemoryStream::getInputStream(  ) throw (RuntimeException)
104 {
105 	return this;
106 }
107 
108 Reference< XOutputStream > SAL_CALL UNOMemoryStream::getOutputStream(  ) throw (RuntimeException)
109 {
110 	return this;
111 }
112 
113 // XInputStream
114 sal_Int32 SAL_CALL UNOMemoryStream::readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
115 {
116 	if( nBytesToRead < 0 )
117 		throw IOException();
118 
119 	nBytesToRead = std::min( nBytesToRead, available() );
120     aData.realloc( nBytesToRead );
121 
122 	if( nBytesToRead )
123 	{
124 		sal_Int8* pData = static_cast<sal_Int8*>(&(*maData.begin()));
125 		sal_Int8* pCursor = &((pData)[mnCursor]);
126 		memcpy( (void*)aData.getArray(), (void*)pCursor, nBytesToRead );
127 
128 		mnCursor += nBytesToRead;
129 	}
130 
131 	return nBytesToRead;
132 }
133 
134 sal_Int32 SAL_CALL UNOMemoryStream::readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
135 {
136 	return readBytes( aData, nMaxBytesToRead );
137 }
138 
139 void SAL_CALL UNOMemoryStream::skipBytes( sal_Int32 nBytesToSkip ) throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
140 {
141 	if( nBytesToSkip < 0 )
142 		throw IOException();
143 
144 	mnCursor += std::min( nBytesToSkip, available() );
145 }
146 
147 sal_Int32 SAL_CALL UNOMemoryStream::available() throw (NotConnectedException, IOException, RuntimeException)
148 {
149 	return static_cast< sal_Int32 >( maData.size() ) - mnCursor;
150 }
151 
152 void SAL_CALL UNOMemoryStream::closeInput() throw (NotConnectedException, IOException, RuntimeException)
153 {
154 	mnCursor = 0;
155 }
156 
157 // XSeekable
158 void SAL_CALL UNOMemoryStream::seek( sal_Int64 location ) throw (IllegalArgumentException, IOException, RuntimeException)
159 {
160 	if( (location < 0) || (location > SAL_MAX_INT32) )
161 		throw IllegalArgumentException( OUString(RTL_CONSTASCII_USTRINGPARAM("this implementation does not support more than 2GB!")), Reference< XInterface >(static_cast<OWeakObject*>(this)), 0 );
162 
163     // seek operation should be able to resize the stream
164     if ( location > static_cast< sal_Int64 >( maData.size() ) )
165         maData.resize( static_cast< sal_Int32 >( location ) );
166 
167     if ( location > static_cast< sal_Int64 >( maData.size() ) )
168         maData.resize( static_cast< sal_Int32 >( location ) );
169 
170 	mnCursor = static_cast< sal_Int32 >( location );
171 }
172 
173 sal_Int64 SAL_CALL UNOMemoryStream::getPosition() throw (IOException, RuntimeException)
174 {
175 	return static_cast< sal_Int64 >( mnCursor );
176 }
177 
178 sal_Int64 SAL_CALL UNOMemoryStream::getLength() throw (IOException, RuntimeException)
179 {
180 	return static_cast< sal_Int64 >( maData.size() );
181 }
182 
183 // XOutputStream
184 void SAL_CALL UNOMemoryStream::writeBytes( const Sequence< sal_Int8 >& aData ) throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
185 {
186 	const sal_Int32 nBytesToWrite( aData.getLength() );
187 	if( nBytesToWrite )
188 	{
189 		sal_Int64 nNewSize = static_cast< sal_Int64 >( mnCursor + nBytesToWrite );
190 		if( nNewSize > SAL_MAX_INT32 )
191 		{
192 			OSL_ASSERT(false);
193 			throw IOException( OUString(RTL_CONSTASCII_USTRINGPARAM("this implementation does not support more than 2GB!")), Reference< XInterface >(static_cast<OWeakObject*>(this)) );
194 		}
195 
196 		if( static_cast< sal_Int32 >( nNewSize ) > static_cast< sal_Int32 >( maData.size() ) )
197 			maData.resize( static_cast< sal_Int32 >( nNewSize ) );
198 
199 		sal_Int8* pData = static_cast<sal_Int8*>(&(*maData.begin()));
200 		sal_Int8* pCursor = &(pData[mnCursor]);
201 		memcpy( (void*)pCursor, (void*)aData.getConstArray(), nBytesToWrite );
202 
203 		mnCursor += nBytesToWrite;
204 	}
205 }
206 
207 void SAL_CALL UNOMemoryStream::flush() throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
208 {
209 }
210 
211 void SAL_CALL UNOMemoryStream::closeOutput() throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
212 {
213 	mnCursor = 0;
214 }
215 
216 //XTruncate
217 void SAL_CALL UNOMemoryStream::truncate() throw (IOException, RuntimeException)
218 {
219     maData.resize( 0 );
220     mnCursor = 0;
221 }
222 
223 ::rtl::OUString SAL_CALL UNOMemoryStream::getImplementationName_static()
224 {
225 	static const OUString sImplName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.MemoryStream" ) );
226 	return sImplName;
227 }
228 
229 Sequence< ::rtl::OUString > SAL_CALL UNOMemoryStream::getSupportedServiceNames_static()
230 {
231 	Sequence< OUString > aSeq(1);
232 	aSeq[0] = getImplementationName_static();
233 	return aSeq;
234 }
235 
236 Reference< XInterface > SAL_CALL UNOMemoryStream::Create(
237     const Reference< XComponentContext >& )
238 {
239 	return static_cast<OWeakObject*>(new UNOMemoryStream());
240 }
241 
242 } // namespace comphelper
243 
244 void createRegistryInfo_UNOMemoryStream()
245 {
246     static ::comphelper::module::OAutoRegistration< ::comphelper::UNOMemoryStream > aAutoRegistration;
247 }
248