/src/libreoffice/unotools/source/streaming/streamwrap.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | #include <sal/config.h> |
21 | | |
22 | | #include <com/sun/star/io/BufferSizeExceededException.hpp> |
23 | | #include <com/sun/star/io/NotConnectedException.hpp> |
24 | | #include <o3tl/safeint.hxx> |
25 | | #include <unotools/streamwrap.hxx> |
26 | | #include <tools/stream.hxx> |
27 | | |
28 | | namespace utl |
29 | | { |
30 | | |
31 | | using namespace ::com::sun::star::uno; |
32 | | using namespace ::com::sun::star::io; |
33 | | using namespace ::com::sun::star::lang; |
34 | | |
35 | | OInputStreamWrapper::OInputStreamWrapper( SvStream& _rStream ) |
36 | 15.1k | :m_pSvStream(&_rStream) |
37 | 15.1k | ,m_bSvStreamOwner(false) |
38 | 15.1k | { |
39 | 15.1k | } |
40 | | |
41 | | OInputStreamWrapper::OInputStreamWrapper( SvStream* pStream, bool bOwner ) |
42 | 18 | :m_pSvStream( pStream ) |
43 | 18 | ,m_bSvStreamOwner( bOwner ) |
44 | 18 | { |
45 | 18 | } |
46 | | |
47 | | OInputStreamWrapper::OInputStreamWrapper( std::unique_ptr<SvStream> pStream ) |
48 | 0 | :m_pSvStream( pStream.release() ) |
49 | 0 | ,m_bSvStreamOwner( true ) |
50 | 0 | { |
51 | 0 | } |
52 | | |
53 | | OInputStreamWrapper::~OInputStreamWrapper() |
54 | 244k | { |
55 | 244k | if( m_bSvStreamOwner ) |
56 | 0 | delete m_pSvStream; |
57 | 244k | } |
58 | | |
59 | | sal_Int32 SAL_CALL OInputStreamWrapper::readBytes(css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) |
60 | 858k | { |
61 | 858k | checkConnected(); |
62 | | |
63 | 858k | if (nBytesToRead < 0) |
64 | 0 | throw css::io::BufferSizeExceededException(OUString(), getXWeak()); |
65 | | |
66 | 858k | std::scoped_lock aGuard( m_aMutex ); |
67 | | |
68 | 858k | if (aData.getLength() < nBytesToRead) |
69 | 213k | aData.realloc(nBytesToRead); |
70 | | |
71 | 858k | sal_uInt32 nRead = m_pSvStream->ReadBytes(static_cast<void*>(aData.getArray()), nBytesToRead); |
72 | 858k | checkError(); |
73 | | |
74 | | // If read characters < MaxLength, adjust css::uno::Sequence |
75 | 858k | if (nRead < o3tl::make_unsigned(aData.getLength())) |
76 | 153k | aData.realloc( nRead ); |
77 | | |
78 | 858k | return nRead; |
79 | 858k | } |
80 | | |
81 | | sal_Int32 OInputStreamWrapper::readSomeBytes(sal_Int8* pData, sal_Int32 nBytesToRead) |
82 | 2.36M | { |
83 | 2.36M | checkConnected(); |
84 | | |
85 | 2.36M | if (nBytesToRead < 0) |
86 | 0 | throw css::io::BufferSizeExceededException(OUString(), getXWeak()); |
87 | | |
88 | 2.36M | std::scoped_lock aGuard( m_aMutex ); |
89 | | |
90 | 2.36M | sal_uInt32 nRead = m_pSvStream->ReadBytes(static_cast<void*>(pData), nBytesToRead); |
91 | 2.36M | checkError(); |
92 | | |
93 | 2.36M | return nRead; |
94 | 2.36M | } |
95 | | |
96 | | sal_Int32 SAL_CALL OInputStreamWrapper::readSomeBytes(css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) |
97 | 276k | { |
98 | 276k | checkError(); |
99 | | |
100 | 276k | if (nMaxBytesToRead < 0) |
101 | 0 | throw css::io::BufferSizeExceededException(OUString(), getXWeak()); |
102 | | |
103 | 276k | if (m_pSvStream->eof()) |
104 | 113k | { |
105 | 113k | aData.realloc(0); |
106 | 113k | return 0; |
107 | 113k | } |
108 | 163k | else |
109 | 163k | return readBytes(aData, nMaxBytesToRead); |
110 | 276k | } |
111 | | |
112 | | void SAL_CALL OInputStreamWrapper::skipBytes(sal_Int32 nBytesToSkip) |
113 | 20.8k | { |
114 | 20.8k | std::scoped_lock aGuard( m_aMutex ); |
115 | 20.8k | checkError(); |
116 | | |
117 | 20.8k | m_pSvStream->SeekRel(nBytesToSkip); |
118 | 20.8k | checkError(); |
119 | 20.8k | } |
120 | | |
121 | | sal_Int32 SAL_CALL OInputStreamWrapper::available() |
122 | 0 | { |
123 | 0 | std::scoped_lock aGuard( m_aMutex ); |
124 | 0 | checkConnected(); |
125 | |
|
126 | 0 | sal_Int64 nAvailable = m_pSvStream->remainingSize(); |
127 | 0 | checkError(); |
128 | |
|
129 | 0 | return std::min<sal_Int64>(SAL_MAX_INT32, nAvailable); |
130 | 0 | } |
131 | | |
132 | | void SAL_CALL OInputStreamWrapper::closeInput() |
133 | 63.2k | { |
134 | 63.2k | std::scoped_lock aGuard( m_aMutex ); |
135 | 63.2k | if (m_pSvStream) |
136 | 63.2k | { |
137 | 63.2k | if (m_bSvStreamOwner) |
138 | 0 | delete m_pSvStream; |
139 | | |
140 | 63.2k | m_pSvStream = nullptr; |
141 | 63.2k | } |
142 | 63.2k | } |
143 | | |
144 | | void OInputStreamWrapper::checkConnected() const |
145 | 13.9M | { |
146 | 13.9M | if (!m_pSvStream) |
147 | 0 | throw css::io::NotConnectedException(OUString(), const_cast<OInputStreamWrapper*>(this)->getXWeak()); |
148 | 13.9M | } |
149 | | |
150 | | void OInputStreamWrapper::checkError() const |
151 | 7.12M | { |
152 | 7.12M | checkConnected(); |
153 | | |
154 | 7.12M | auto const e = m_pSvStream->SvStream::GetError(); |
155 | 7.12M | if (e != ERRCODE_NONE) |
156 | | // TODO: really evaluate the error |
157 | 0 | throw css::io::NotConnectedException("utl::OInputStreamWrapper error " + e.toString(), const_cast<OInputStreamWrapper*>(this)->getXWeak()); |
158 | 7.12M | } |
159 | | |
160 | | //= OSeekableInputStreamWrapper |
161 | | |
162 | 229k | OSeekableInputStreamWrapper::~OSeekableInputStreamWrapper() = default; |
163 | | |
164 | | OSeekableInputStreamWrapper::OSeekableInputStreamWrapper(SvStream& _rStream) |
165 | 212k | { |
166 | 212k | SetStream( &_rStream, false ); |
167 | 212k | } |
168 | | |
169 | | OSeekableInputStreamWrapper::OSeekableInputStreamWrapper(SvStream* _pStream, bool _bOwner) |
170 | 8 | { |
171 | 8 | SetStream( _pStream, _bOwner ); |
172 | 8 | } |
173 | | |
174 | | void SAL_CALL OSeekableInputStreamWrapper::seek( sal_Int64 _nLocation ) |
175 | 1.69M | { |
176 | 1.69M | std::scoped_lock aGuard( m_aMutex ); |
177 | 1.69M | checkConnected(); |
178 | | |
179 | 1.69M | m_pSvStream->Seek(static_cast<sal_uInt64>(_nLocation)); |
180 | 1.69M | checkError(); |
181 | 1.69M | } |
182 | | |
183 | | sal_Int64 SAL_CALL OSeekableInputStreamWrapper::getPosition( ) |
184 | 958k | { |
185 | 958k | std::scoped_lock aGuard( m_aMutex ); |
186 | 958k | checkConnected(); |
187 | | |
188 | 958k | sal_uInt64 nPos = m_pSvStream->Tell(); |
189 | 958k | checkError(); |
190 | 958k | return static_cast<sal_Int64>(nPos); |
191 | 958k | } |
192 | | |
193 | | sal_Int64 SAL_CALL OSeekableInputStreamWrapper::getLength( ) |
194 | 935k | { |
195 | 935k | std::scoped_lock aGuard( m_aMutex ); |
196 | 935k | checkConnected(); |
197 | | |
198 | 935k | checkError(); |
199 | | |
200 | 935k | sal_Int64 nEndPos = m_pSvStream->TellEnd(); |
201 | | |
202 | 935k | return nEndPos; |
203 | 935k | } |
204 | | |
205 | | //= OOutputStreamWrapper |
206 | | |
207 | | OOutputStreamWrapper::OOutputStreamWrapper(SvStream& _rStream): |
208 | 307 | rStream(_rStream) |
209 | 307 | {} |
210 | | |
211 | 307 | OOutputStreamWrapper::~OOutputStreamWrapper() {} |
212 | | |
213 | | void SAL_CALL OOutputStreamWrapper::writeBytes(const css::uno::Sequence< sal_Int8 >& aData) |
214 | 284 | { |
215 | 284 | sal_uInt32 nWritten = rStream.WriteBytes(aData.getConstArray(), aData.getLength()); |
216 | 284 | ErrCode err = rStream.GetError(); |
217 | 284 | if ( (ERRCODE_NONE != err) |
218 | 284 | || (nWritten != static_cast<sal_uInt32>(aData.getLength())) |
219 | 284 | ) |
220 | 0 | { |
221 | 0 | throw css::io::BufferSizeExceededException(OUString(), getXWeak()); |
222 | 0 | } |
223 | 284 | } |
224 | | |
225 | | void SAL_CALL OOutputStreamWrapper::flush() |
226 | 0 | { |
227 | 0 | rStream.FlushBuffer(); |
228 | 0 | checkError(); |
229 | 0 | } |
230 | | |
231 | | void SAL_CALL OOutputStreamWrapper::closeOutput() |
232 | 266 | { |
233 | 266 | } |
234 | | |
235 | | void OOutputStreamWrapper::checkError() const |
236 | 0 | { |
237 | 0 | if (rStream.GetError() != ERRCODE_NONE) |
238 | | // TODO: really evaluate the error |
239 | 0 | throw css::io::NotConnectedException(OUString(), const_cast<OOutputStreamWrapper*>(this)->getXWeak()); |
240 | 0 | } |
241 | | |
242 | | //= OSeekableOutputStreamWrapper |
243 | | |
244 | | OSeekableOutputStreamWrapper::OSeekableOutputStreamWrapper(SvStream& _rStream) |
245 | 0 | :OOutputStreamWrapper(_rStream) |
246 | 0 | { |
247 | 0 | } |
248 | | |
249 | 0 | OSeekableOutputStreamWrapper::~OSeekableOutputStreamWrapper() {} |
250 | | |
251 | | Any SAL_CALL OSeekableOutputStreamWrapper::queryInterface( const Type& _rType ) |
252 | 0 | { |
253 | 0 | Any aReturn = OOutputStreamWrapper::queryInterface(_rType); |
254 | 0 | if (!aReturn.hasValue()) |
255 | 0 | aReturn = OSeekableOutputStreamWrapper_Base::queryInterface(_rType); |
256 | 0 | return aReturn; |
257 | 0 | } |
258 | | |
259 | | void SAL_CALL OSeekableOutputStreamWrapper::seek( sal_Int64 _nLocation ) |
260 | 0 | { |
261 | 0 | rStream.Seek(static_cast<sal_uInt32>(_nLocation)); |
262 | 0 | checkError(); |
263 | 0 | } |
264 | | |
265 | | sal_Int64 SAL_CALL OSeekableOutputStreamWrapper::getPosition( ) |
266 | 0 | { |
267 | 0 | sal_uInt64 nPos = rStream.Tell(); |
268 | 0 | checkError(); |
269 | 0 | return static_cast<sal_Int64>(nPos); |
270 | 0 | } |
271 | | |
272 | | sal_Int64 SAL_CALL OSeekableOutputStreamWrapper::getLength( ) |
273 | 0 | { |
274 | 0 | checkError(); |
275 | |
|
276 | 0 | sal_Int64 nEndPos = rStream.TellEnd(); |
277 | |
|
278 | 0 | return nEndPos; |
279 | 0 | } |
280 | | |
281 | 16.9k | OStreamWrapper::~OStreamWrapper() = default; |
282 | | |
283 | | OStreamWrapper::OStreamWrapper(SvStream& _rStream) |
284 | 16.2k | { |
285 | 16.2k | SetStream( &_rStream, false ); |
286 | 16.2k | } |
287 | | |
288 | | OStreamWrapper::OStreamWrapper(std::unique_ptr<SvStream> pStream) |
289 | 0 | { |
290 | 0 | SetStream( pStream.release(), true ); |
291 | 0 | } |
292 | | |
293 | | OStreamWrapper::OStreamWrapper(SvStream* pStream, bool bOwner) |
294 | 751 | { |
295 | 751 | SetStream( pStream, bOwner ); |
296 | 751 | } |
297 | | |
298 | | css::uno::Reference< css::io::XInputStream > SAL_CALL OStreamWrapper::getInputStream( ) |
299 | 8 | { |
300 | 8 | return this; |
301 | 8 | } |
302 | | |
303 | | css::uno::Reference< css::io::XOutputStream > SAL_CALL OStreamWrapper::getOutputStream( ) |
304 | 139 | { |
305 | 139 | return this; |
306 | 139 | } |
307 | | |
308 | | void SAL_CALL OStreamWrapper::writeBytes(const css::uno::Sequence< sal_Int8 >& aData) |
309 | 5.55k | { |
310 | 5.55k | sal_uInt32 nWritten = m_pSvStream->WriteBytes(aData.getConstArray(), aData.getLength()); |
311 | 5.55k | ErrCode err = m_pSvStream->GetError(); |
312 | 5.55k | if ( (ERRCODE_NONE != err) |
313 | 5.55k | || (nWritten != static_cast<sal_uInt32>(aData.getLength())) |
314 | 5.55k | ) |
315 | 0 | { |
316 | 0 | throw css::io::BufferSizeExceededException(OUString(), getXWeak()); |
317 | 0 | } |
318 | 5.55k | } |
319 | | |
320 | | void SAL_CALL OStreamWrapper::flush() |
321 | 4 | { |
322 | 4 | m_pSvStream->FlushBuffer(); |
323 | 4 | if (m_pSvStream->GetError() != ERRCODE_NONE) |
324 | 0 | throw css::io::NotConnectedException(OUString(), getXWeak()); |
325 | 4 | } |
326 | | |
327 | | void SAL_CALL OStreamWrapper::closeOutput() |
328 | 4.39k | { |
329 | 4.39k | } |
330 | | |
331 | | void SAL_CALL OStreamWrapper::truncate() |
332 | 0 | { |
333 | 0 | m_pSvStream->SetStreamSize(0); |
334 | 0 | } |
335 | | |
336 | | } // namespace utl |
337 | | |
338 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |