LibreOffice Module comphelper (master) 1
memorystream.cxx
Go to the documentation of this file.
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 <algorithm>
21#include <memory>
22
23#include <boost/core/noinit_adaptor.hpp>
24
25#include <com/sun/star/lang/IllegalArgumentException.hpp>
26#include <com/sun/star/lang/XServiceInfo.hpp>
27#include <com/sun/star/lang/XUnoTunnel.hpp>
28#include <com/sun/star/io/IOException.hpp>
29#include <com/sun/star/io/XStream.hpp>
30#include <com/sun/star/io/XSeekableInputStream.hpp>
31#include <com/sun/star/io/XTruncate.hpp>
32//#include <com/sun/star/uno/XComponentContext.hpp>
36#include <o3tl/safeint.hxx>
37#include <osl/diagnose.h>
38
39#include <string.h>
40#include <vector>
41
42namespace com::sun::star::uno { class XComponentContext; }
43
44using ::cppu::OWeakObject;
45using ::cppu::WeakImplHelper;
46using namespace ::com::sun::star::io;
47using namespace ::com::sun::star::uno;
48using namespace ::com::sun::star::lang;
49using namespace ::osl;
50
51namespace comphelper
52{
53
54namespace {
55
56class UNOMemoryStream :
57 public WeakImplHelper<XServiceInfo, XStream, XSeekableInputStream, XOutputStream, XTruncate, XUnoTunnel>,
59{
60public:
61 UNOMemoryStream();
62
63 // XServiceInfo
64 virtual OUString SAL_CALL getImplementationName() override;
65 virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
66 virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
67
68 // XStream
69 virtual Reference< XInputStream > SAL_CALL getInputStream( ) override;
70 virtual Reference< XOutputStream > SAL_CALL getOutputStream( ) override;
71
72 // XInputStream
73 virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) override;
74 virtual sal_Int32 SAL_CALL readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) override;
75 virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) override;
76 virtual sal_Int32 SAL_CALL available() override;
77 virtual void SAL_CALL closeInput() override;
78
79 // XSeekable
80 virtual void SAL_CALL seek( sal_Int64 location ) override;
81 virtual sal_Int64 SAL_CALL getPosition() override;
82 virtual sal_Int64 SAL_CALL getLength() override;
83
84 // XOutputStream
85 virtual void SAL_CALL writeBytes( const Sequence< sal_Int8 >& aData ) override;
86 virtual void SAL_CALL flush() override;
87 virtual void SAL_CALL closeOutput() override;
88
89 // XTruncate
90 virtual void SAL_CALL truncate() override;
91
92 // XUnoTunnel
93 virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override;
94
95 // comphelper::ByteWriter
96 virtual sal_Int32 writeSomeBytes(const sal_Int8* aData, sal_Int32 nBytesToWrite) override;
97
98private:
99 std::vector< sal_Int8, boost::noinit_adaptor<std::allocator<sal_Int8>> > maData;
100 sal_Int32 mnCursor;
101};
102
103}
104
105UNOMemoryStream::UNOMemoryStream()
106: mnCursor(0)
107{
108 maData.reserve(1 * 1024 * 1024);
109}
110
111// XServiceInfo
112OUString SAL_CALL UNOMemoryStream::getImplementationName()
113{
114 return "com.sun.star.comp.MemoryStream";
115}
116
117sal_Bool SAL_CALL UNOMemoryStream::supportsService(const OUString& ServiceName)
118{
119 return cppu::supportsService(this, ServiceName);
120}
121
122css::uno::Sequence<OUString> SAL_CALL UNOMemoryStream::getSupportedServiceNames()
123{
124 return { "com.sun.star.comp.MemoryStream" };
125}
126
127// XStream
128Reference< XInputStream > SAL_CALL UNOMemoryStream::getInputStream( )
129{
130 return this;
131}
132
133Reference< XOutputStream > SAL_CALL UNOMemoryStream::getOutputStream( )
134{
135 return this;
136}
137
138// XInputStream
139sal_Int32 SAL_CALL UNOMemoryStream::readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
140{
141 if( nBytesToRead < 0 )
142 throw IOException("nBytesToRead < 0");
143
144 nBytesToRead = std::min( nBytesToRead, available() );
145 aData.realloc( nBytesToRead );
146
147 if( nBytesToRead )
148 {
149 sal_Int8* pData = &(*maData.begin());
150 sal_Int8* pCursor = &(pData[mnCursor]);
151 memcpy( aData.getArray(), pCursor, nBytesToRead );
152
153 mnCursor += nBytesToRead;
154 }
155
156 return nBytesToRead;
157}
158
159sal_Int32 SAL_CALL UNOMemoryStream::readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
160{
161 return readBytes( aData, nMaxBytesToRead );
162}
163
164void SAL_CALL UNOMemoryStream::skipBytes( sal_Int32 nBytesToSkip )
165{
166 if( nBytesToSkip < 0 )
167 throw IOException("nBytesToSkip < 0");
168
169 mnCursor += std::min( nBytesToSkip, available() );
170}
171
172sal_Int32 SAL_CALL UNOMemoryStream::available()
173{
174 return std::min<sal_Int64>( SAL_MAX_INT32, maData.size() - mnCursor);
175}
176
177void SAL_CALL UNOMemoryStream::closeInput()
178{
179 mnCursor = 0;
180}
181
182// XSeekable
183void SAL_CALL UNOMemoryStream::seek( sal_Int64 location )
184{
185 if( (location < 0) || (location > SAL_MAX_INT32) )
186 throw IllegalArgumentException("this implementation does not support more than 2GB!", static_cast<OWeakObject*>(this), 0 );
187
188 // seek operation should be able to resize the stream
189 if ( o3tl::make_unsigned(location) > maData.size() )
190 maData.resize( static_cast< sal_Int32 >( location ) );
191
192 mnCursor = static_cast< sal_Int32 >( location );
193}
194
195sal_Int64 SAL_CALL UNOMemoryStream::getPosition()
196{
197 return static_cast< sal_Int64 >( mnCursor );
198}
199
200sal_Int64 SAL_CALL UNOMemoryStream::getLength()
201{
202 return static_cast< sal_Int64 >( maData.size() );
203}
204
205// XOutputStream
206void SAL_CALL UNOMemoryStream::writeBytes( const Sequence< sal_Int8 >& aData )
207{
208 const sal_Int32 nBytesToWrite( aData.getLength() );
209 if( !nBytesToWrite )
210 return;
211
212 sal_Int64 nNewSize = static_cast<sal_Int64>(mnCursor) + nBytesToWrite;
213 if( nNewSize > SAL_MAX_INT32 )
214 {
215 OSL_ASSERT(false);
216 throw IOException("this implementation does not support more than 2GB!", static_cast<OWeakObject*>(this) );
217 }
218
219 if( static_cast< sal_Int32 >( nNewSize ) > static_cast< sal_Int32 >( maData.size() ) )
220 maData.resize( nNewSize );
221
222 sal_Int8* pData = &(*maData.begin());
223 sal_Int8* pCursor = &(pData[mnCursor]);
224 memcpy(pCursor, aData.getConstArray(), nBytesToWrite);
225
226 mnCursor += nBytesToWrite;
227}
228
229sal_Int32 UNOMemoryStream::writeSomeBytes( const sal_Int8* pInData, sal_Int32 nBytesToWrite )
230{
231 if( !nBytesToWrite )
232 return 0;
233
234 sal_Int64 nNewSize = static_cast<sal_Int64>(mnCursor) + nBytesToWrite;
235 if( nNewSize > SAL_MAX_INT32 )
236 {
237 OSL_ASSERT(false);
238 throw IOException("this implementation does not support more than 2GB!", static_cast<OWeakObject*>(this) );
239 }
240
241 if( static_cast< sal_Int32 >( nNewSize ) > static_cast< sal_Int32 >( maData.size() ) )
242 maData.resize( nNewSize );
243
244 sal_Int8* pData = &(*maData.begin());
245 sal_Int8* pCursor = &(pData[mnCursor]);
246 // cast to avoid -Werror=class-memaccess
247 memcpy(pCursor, pInData, nBytesToWrite);
248
249 mnCursor += nBytesToWrite;
250 return nBytesToWrite;
251}
252
253void SAL_CALL UNOMemoryStream::flush()
254{
255}
256
257void SAL_CALL UNOMemoryStream::closeOutput()
258{
259 mnCursor = 0;
260}
261
262//XTruncate
263void SAL_CALL UNOMemoryStream::truncate()
264{
265 maData.clear();
266 mnCursor = 0;
267}
268
269sal_Int64 SAL_CALL UNOMemoryStream::getSomething( const css::uno::Sequence< sal_Int8 >& rIdentifier )
270{
271 if (rIdentifier == comphelper::ByteWriter::getUnoTunnelId())
272 return reinterpret_cast<sal_Int64>(static_cast<comphelper::ByteWriter*>(this));
273 return 0;
274}
275
276} // namespace comphelper
277
278extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
280 css::uno::XComponentContext *,
281 css::uno::Sequence<css::uno::Any> const &)
282{
283 return cppu::acquire(new ::comphelper::UNOMemoryStream());
284}
285
286/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Interface that we can cast to, to bypass the inefficiency of using Sequence<sal_Int8> when writing vi...
Definition: bytereader.hxx:34
static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId()
Definition: basicio.cxx:172
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_MemoryStream(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
sal_Int32 mnCursor
std::vector< sal_Int8, boost::noinit_adaptor< std::allocator< sal_Int8 > > > maData
std::unique_ptr< sal_Int32[]> pData
constexpr OUStringLiteral aData
double getLength(const B2DPolygon &rCandidate)
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
bool getOutputStream(ProgramOptions const &options, OString const &extension, std::ostream **ppOutputStream, OString &targetSourceFileName, OString &tmpSourceFileName)
unsigned char sal_Bool
signed char sal_Int8