diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /comphelper/source/streaming | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comphelper/source/streaming')
-rw-r--r-- | comphelper/source/streaming/basicio.cxx | 182 | ||||
-rw-r--r-- | comphelper/source/streaming/memorystream.cxx | 286 | ||||
-rw-r--r-- | comphelper/source/streaming/oslfile2streamwrap.cxx | 171 | ||||
-rw-r--r-- | comphelper/source/streaming/seekableinput.cxx | 233 | ||||
-rw-r--r-- | comphelper/source/streaming/seqinputstreamserv.cxx | 215 | ||||
-rw-r--r-- | comphelper/source/streaming/seqoutputstreamserv.cxx | 144 | ||||
-rw-r--r-- | comphelper/source/streaming/seqstream.cxx | 247 | ||||
-rw-r--r-- | comphelper/source/streaming/streamsection.cxx | 91 |
8 files changed, 1569 insertions, 0 deletions
diff --git a/comphelper/source/streaming/basicio.cxx b/comphelper/source/streaming/basicio.cxx new file mode 100644 index 000000000..b8c0c96e2 --- /dev/null +++ b/comphelper/source/streaming/basicio.cxx @@ -0,0 +1,182 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <comphelper/basicio.hxx> +#include <comphelper/bytereader.hxx> +#include <comphelper/servicehelper.hxx> +#include <com/sun/star/awt/FontDescriptor.hpp> + +namespace comphelper +{ + + +const css::uno::Reference<css::io::XObjectOutputStream>& operator << ( + const css::uno::Reference<css::io::XObjectOutputStream>& _rxOutStream, + const css::awt::FontDescriptor& _rFont) +{ + _rxOutStream->writeUTF( _rFont.Name ); + _rxOutStream->writeShort( _rFont.Height ); + _rxOutStream->writeShort( _rFont.Width ); + _rxOutStream->writeUTF( _rFont.StyleName ); + _rxOutStream->writeShort( _rFont.Family ); + _rxOutStream->writeShort( _rFont.CharSet ); + _rxOutStream->writeShort( _rFont.Pitch ); + _rxOutStream->writeDouble( _rFont.CharacterWidth ); + _rxOutStream->writeDouble( _rFont.Weight ); + _rxOutStream->writeShort( static_cast< sal_Int16 >(_rFont.Slant) ); + _rxOutStream->writeShort( _rFont.Underline ); + _rxOutStream->writeShort( _rFont.Strikeout ); + _rxOutStream->writeDouble( _rFont.Orientation ); + _rxOutStream->writeBoolean( _rFont.Kerning ); + _rxOutStream->writeBoolean( _rFont.WordLineMode ); + _rxOutStream->writeShort( _rFont.Type ); + return _rxOutStream; +} + +// FontDescriptor + +const css::uno::Reference<css::io::XObjectInputStream>& operator >> ( + const css::uno::Reference<css::io::XObjectInputStream>& _rxInStream, + css::awt::FontDescriptor& _rFont) +{ + // writing the FontDescriptor + _rFont.Name = _rxInStream->readUTF(); + _rFont.Height = _rxInStream->readShort(); + _rFont.Width = _rxInStream->readShort(); + _rFont.StyleName = _rxInStream->readUTF(); + _rFont.Family = _rxInStream->readShort(); + _rFont.CharSet = _rxInStream->readShort(); + _rFont.Pitch = _rxInStream->readShort(); + _rFont.CharacterWidth = static_cast< float >(_rxInStream->readDouble()); + _rFont.Weight = static_cast< float >(_rxInStream->readDouble()); + _rFont.Slant = static_cast<css::awt::FontSlant>(_rxInStream->readShort()); + _rFont.Underline = _rxInStream->readShort(); + _rFont.Strikeout = _rxInStream->readShort(); + _rFont.Orientation = static_cast< float >(_rxInStream->readDouble()); + _rFont.Kerning = _rxInStream->readBoolean() != 0; + _rFont.WordLineMode = _rxInStream->readBoolean() != 0; + _rFont.Type = _rxInStream->readShort(); + return _rxInStream; +} + + +const css::uno::Reference<css::io::XObjectInputStream>& operator >> (const css::uno::Reference<css::io::XObjectInputStream>& _rxInStream, bool& _rVal) +{ + _rVal = _rxInStream->readBoolean(); + return _rxInStream; +} + + +const css::uno::Reference<css::io::XObjectOutputStream>& operator << (const css::uno::Reference<css::io::XObjectOutputStream>& _rxOutStream, bool _bVal) +{ + _rxOutStream->writeBoolean(_bVal); + return _rxOutStream; +} + + +const css::uno::Reference<css::io::XObjectInputStream>& operator >> (const css::uno::Reference<css::io::XObjectInputStream>& _rxInStream, OUString& rStr) +{ + rStr = _rxInStream->readUTF(); + return _rxInStream; +} + + +const css::uno::Reference<css::io::XObjectOutputStream>& operator << (const css::uno::Reference<css::io::XObjectOutputStream>& _rxOutStream, const OUString& rStr) +{ + _rxOutStream->writeUTF(rStr); + return _rxOutStream; +} + + +const css::uno::Reference<css::io::XObjectInputStream>& operator >> (const css::uno::Reference<css::io::XObjectInputStream>& _rxInStream, sal_Int16& _rValue) +{ + _rValue = _rxInStream->readShort(); + return _rxInStream; +} + + +const css::uno::Reference<css::io::XObjectOutputStream>& operator << (const css::uno::Reference<css::io::XObjectOutputStream>& _rxOutStream, sal_Int16 _nValue) +{ + _rxOutStream->writeShort(_nValue); + return _rxOutStream; +} + + +const css::uno::Reference<css::io::XObjectInputStream>& operator >> (const css::uno::Reference<css::io::XObjectInputStream>& _rxInStream, sal_uInt16& _rValue) +{ + _rValue = _rxInStream->readShort(); + return _rxInStream; +} + + +const css::uno::Reference<css::io::XObjectOutputStream>& operator << (const css::uno::Reference<css::io::XObjectOutputStream>& _rxOutStream, sal_uInt16 _nValue) +{ + _rxOutStream->writeShort(_nValue); + return _rxOutStream; +} + + +const css::uno::Reference<css::io::XObjectInputStream>& operator >> (const css::uno::Reference<css::io::XObjectInputStream>& _rxInStream, sal_uInt32& _rValue) +{ + _rValue = _rxInStream->readLong(); + return _rxInStream; +} + + +const css::uno::Reference<css::io::XObjectOutputStream>& operator << (const css::uno::Reference<css::io::XObjectOutputStream>& _rxOutStream, sal_uInt32 _nValue) +{ + _rxOutStream->writeLong(_nValue); + return _rxOutStream; +} + + +const css::uno::Reference<css::io::XObjectInputStream>& operator >> (const css::uno::Reference<css::io::XObjectInputStream>& _rxInStream, sal_Int32& _rValue) +{ + _rValue = _rxInStream->readLong(); + return _rxInStream; +} + + +const css::uno::Reference<css::io::XObjectOutputStream>& operator << (const css::uno::Reference<css::io::XObjectOutputStream>& _rxOutStream, sal_Int32 _nValue) +{ + _rxOutStream->writeLong(_nValue); + return _rxOutStream; +} + +ByteReader::~ByteReader() {} + +const css::uno::Sequence< sal_Int8 > & ByteReader::getUnoTunnelId() +{ + static const comphelper::UnoIdInit implId; + return implId.getSeq(); +} + +ByteWriter::~ByteWriter() {} + +const css::uno::Sequence< sal_Int8 > & ByteWriter::getUnoTunnelId() +{ + static const comphelper::UnoIdInit implId; + return implId.getSeq(); +} + + +} // namespace comphelper + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/streaming/memorystream.cxx b/comphelper/source/streaming/memorystream.cxx new file mode 100644 index 000000000..8bf3c3e90 --- /dev/null +++ b/comphelper/source/streaming/memorystream.cxx @@ -0,0 +1,286 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <algorithm> +#include <memory> + +#include <boost/core/noinit_adaptor.hpp> + +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/io/IOException.hpp> +#include <com/sun/star/io/XStream.hpp> +#include <com/sun/star/io/XSeekableInputStream.hpp> +#include <com/sun/star/io/XTruncate.hpp> +//#include <com/sun/star/uno/XComponentContext.hpp> +#include <comphelper/bytereader.hxx> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <o3tl/safeint.hxx> +#include <osl/diagnose.h> + +#include <string.h> +#include <vector> + +namespace com::sun::star::uno { class XComponentContext; } + +using ::cppu::OWeakObject; +using ::cppu::WeakImplHelper; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::osl; + +namespace comphelper +{ + +namespace { + +class UNOMemoryStream : + public WeakImplHelper<XServiceInfo, XStream, XSeekableInputStream, XOutputStream, XTruncate, XUnoTunnel>, + public comphelper::ByteWriter +{ +public: + UNOMemoryStream(); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; + + // XStream + virtual Reference< XInputStream > SAL_CALL getInputStream( ) override; + virtual Reference< XOutputStream > SAL_CALL getOutputStream( ) override; + + // XInputStream + virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) override; + virtual sal_Int32 SAL_CALL readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) override; + virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) override; + virtual sal_Int32 SAL_CALL available() override; + virtual void SAL_CALL closeInput() override; + + // XSeekable + virtual void SAL_CALL seek( sal_Int64 location ) override; + virtual sal_Int64 SAL_CALL getPosition() override; + virtual sal_Int64 SAL_CALL getLength() override; + + // XOutputStream + virtual void SAL_CALL writeBytes( const Sequence< sal_Int8 >& aData ) override; + virtual void SAL_CALL flush() override; + virtual void SAL_CALL closeOutput() override; + + // XTruncate + virtual void SAL_CALL truncate() override; + + // XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override; + + // comphelper::ByteWriter + virtual sal_Int32 writeSomeBytes(const sal_Int8* aData, sal_Int32 nBytesToWrite) override; + +private: + std::vector< sal_Int8, boost::noinit_adaptor<std::allocator<sal_Int8>> > maData; + sal_Int32 mnCursor; +}; + +} + +UNOMemoryStream::UNOMemoryStream() +: mnCursor(0) +{ + maData.reserve(1 * 1024 * 1024); +} + +// XServiceInfo +OUString SAL_CALL UNOMemoryStream::getImplementationName() +{ + return "com.sun.star.comp.MemoryStream"; +} + +sal_Bool SAL_CALL UNOMemoryStream::supportsService(const OUString& ServiceName) +{ + return cppu::supportsService(this, ServiceName); +} + +css::uno::Sequence<OUString> SAL_CALL UNOMemoryStream::getSupportedServiceNames() +{ + return { "com.sun.star.comp.MemoryStream" }; +} + +// XStream +Reference< XInputStream > SAL_CALL UNOMemoryStream::getInputStream( ) +{ + return this; +} + +Reference< XOutputStream > SAL_CALL UNOMemoryStream::getOutputStream( ) +{ + return this; +} + +// XInputStream +sal_Int32 SAL_CALL UNOMemoryStream::readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) +{ + if( nBytesToRead < 0 ) + throw IOException("nBytesToRead < 0"); + + nBytesToRead = std::min( nBytesToRead, available() ); + aData.realloc( nBytesToRead ); + + if( nBytesToRead ) + { + sal_Int8* pData = &(*maData.begin()); + sal_Int8* pCursor = &(pData[mnCursor]); + memcpy( aData.getArray(), pCursor, nBytesToRead ); + + mnCursor += nBytesToRead; + } + + return nBytesToRead; +} + +sal_Int32 SAL_CALL UNOMemoryStream::readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) +{ + return readBytes( aData, nMaxBytesToRead ); +} + +void SAL_CALL UNOMemoryStream::skipBytes( sal_Int32 nBytesToSkip ) +{ + if( nBytesToSkip < 0 ) + throw IOException("nBytesToSkip < 0"); + + mnCursor += std::min( nBytesToSkip, available() ); +} + +sal_Int32 SAL_CALL UNOMemoryStream::available() +{ + return std::min<sal_Int64>( SAL_MAX_INT32, maData.size() - mnCursor); +} + +void SAL_CALL UNOMemoryStream::closeInput() +{ + mnCursor = 0; +} + +// XSeekable +void SAL_CALL UNOMemoryStream::seek( sal_Int64 location ) +{ + if( (location < 0) || (location > SAL_MAX_INT32) ) + throw IllegalArgumentException("this implementation does not support more than 2GB!", static_cast<OWeakObject*>(this), 0 ); + + // seek operation should be able to resize the stream + if ( o3tl::make_unsigned(location) > maData.size() ) + maData.resize( static_cast< sal_Int32 >( location ) ); + + mnCursor = static_cast< sal_Int32 >( location ); +} + +sal_Int64 SAL_CALL UNOMemoryStream::getPosition() +{ + return static_cast< sal_Int64 >( mnCursor ); +} + +sal_Int64 SAL_CALL UNOMemoryStream::getLength() +{ + return static_cast< sal_Int64 >( maData.size() ); +} + +// XOutputStream +void SAL_CALL UNOMemoryStream::writeBytes( const Sequence< sal_Int8 >& aData ) +{ + const sal_Int32 nBytesToWrite( aData.getLength() ); + if( !nBytesToWrite ) + return; + + sal_Int64 nNewSize = static_cast<sal_Int64>(mnCursor) + nBytesToWrite; + if( nNewSize > SAL_MAX_INT32 ) + { + OSL_ASSERT(false); + throw IOException("this implementation does not support more than 2GB!", static_cast<OWeakObject*>(this) ); + } + + if( static_cast< sal_Int32 >( nNewSize ) > static_cast< sal_Int32 >( maData.size() ) ) + maData.resize( nNewSize ); + + sal_Int8* pData = &(*maData.begin()); + sal_Int8* pCursor = &(pData[mnCursor]); + memcpy(pCursor, aData.getConstArray(), nBytesToWrite); + + mnCursor += nBytesToWrite; +} + +sal_Int32 UNOMemoryStream::writeSomeBytes( const sal_Int8* pInData, sal_Int32 nBytesToWrite ) +{ + if( !nBytesToWrite ) + return 0; + + sal_Int64 nNewSize = static_cast<sal_Int64>(mnCursor) + nBytesToWrite; + if( nNewSize > SAL_MAX_INT32 ) + { + OSL_ASSERT(false); + throw IOException("this implementation does not support more than 2GB!", static_cast<OWeakObject*>(this) ); + } + + if( static_cast< sal_Int32 >( nNewSize ) > static_cast< sal_Int32 >( maData.size() ) ) + maData.resize( nNewSize ); + + sal_Int8* pData = &(*maData.begin()); + sal_Int8* pCursor = &(pData[mnCursor]); + // cast to avoid -Werror=class-memaccess + memcpy(pCursor, pInData, nBytesToWrite); + + mnCursor += nBytesToWrite; + return nBytesToWrite; +} + +void SAL_CALL UNOMemoryStream::flush() +{ +} + +void SAL_CALL UNOMemoryStream::closeOutput() +{ + mnCursor = 0; +} + +//XTruncate +void SAL_CALL UNOMemoryStream::truncate() +{ + maData.clear(); + mnCursor = 0; +} + +sal_Int64 SAL_CALL UNOMemoryStream::getSomething( const css::uno::Sequence< sal_Int8 >& rIdentifier ) +{ + if (rIdentifier == comphelper::ByteWriter::getUnoTunnelId()) + return reinterpret_cast<sal_Int64>(static_cast<comphelper::ByteWriter*>(this)); + return 0; +} + +} // namespace comphelper + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_MemoryStream( + css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::comphelper::UNOMemoryStream()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/streaming/oslfile2streamwrap.cxx b/comphelper/source/streaming/oslfile2streamwrap.cxx new file mode 100644 index 000000000..243634610 --- /dev/null +++ b/comphelper/source/streaming/oslfile2streamwrap.cxx @@ -0,0 +1,171 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <com/sun/star/io/BufferSizeExceededException.hpp> +#include <com/sun/star/io/NotConnectedException.hpp> +#include <comphelper/oslfile2streamwrap.hxx> +#include <o3tl/safeint.hxx> +#include <osl/file.hxx> + +#include <algorithm> + +namespace comphelper +{ + using namespace osl; + + +OSLInputStreamWrapper::OSLInputStreamWrapper( File& _rFile ) + : m_pFile(&_rFile) +{ +} + + +OSLInputStreamWrapper::~OSLInputStreamWrapper() +{ +} + + +sal_Int32 SAL_CALL OSLInputStreamWrapper::readBytes(css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) +{ + if (!m_pFile) + throw css::io::NotConnectedException(OUString(), static_cast<css::uno::XWeak*>(this)); + + if (nBytesToRead < 0) + throw css::io::BufferSizeExceededException(OUString(),static_cast<css::uno::XWeak*>(this)); + + aData.realloc(nBytesToRead); + + std::scoped_lock aGuard( m_aMutex ); + + sal_uInt64 nRead = 0; + FileBase::RC eError = m_pFile->read(static_cast<void*>(aData.getArray()), nBytesToRead, nRead); + if (eError != FileBase::E_None) + throw css::io::BufferSizeExceededException(OUString(),static_cast<css::uno::XWeak*>(this)); + + // If the read character < MaxLength, adjust css::uno::Sequence + if (nRead < o3tl::make_unsigned(nBytesToRead)) + aData.realloc( sal::static_int_cast< sal_Int32 >(nRead) ); + + return sal::static_int_cast< sal_Int32 >(nRead); +} + +sal_Int32 SAL_CALL OSLInputStreamWrapper::readSomeBytes(css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) +{ + if (!m_pFile) + throw css::io::NotConnectedException(OUString(), static_cast<css::uno::XWeak*>(this)); + + if (nMaxBytesToRead < 0) + throw css::io::BufferSizeExceededException(OUString(),static_cast<css::uno::XWeak*>(this)); + + return readBytes(aData, nMaxBytesToRead); +} + +void SAL_CALL OSLInputStreamWrapper::skipBytes(sal_Int32 nBytesToSkip) +{ + std::scoped_lock aGuard( m_aMutex ); + if (!m_pFile) + throw css::io::NotConnectedException(OUString(), static_cast<css::uno::XWeak*>(this)); + + sal_uInt64 nCurrentPos; + FileBase::RC eError = m_pFile->getPos(nCurrentPos); + if (eError != FileBase::E_None) + throw css::io::NotConnectedException(OUString(), static_cast<css::uno::XWeak*>(this)); + + sal_uInt64 nNewPos = nCurrentPos + nBytesToSkip; + eError = m_pFile->setPos(osl_Pos_Absolut, nNewPos); + if (eError != FileBase::E_None) + throw css::io::NotConnectedException(OUString(), static_cast<css::uno::XWeak*>(this)); +} + +sal_Int32 SAL_CALL OSLInputStreamWrapper::available() +{ + std::scoped_lock aGuard( m_aMutex ); + if (!m_pFile) + throw css::io::NotConnectedException(OUString(), static_cast<css::uno::XWeak*>(this)); + + sal_uInt64 nPos; + FileBase::RC eError = m_pFile->getPos(nPos); + if (eError != FileBase::E_None) + throw css::io::NotConnectedException(OUString(), static_cast<css::uno::XWeak*>(this)); + + eError = m_pFile->setPos(osl_Pos_End, 0); + if (eError != FileBase::E_None) + throw css::io::NotConnectedException(OUString(),static_cast<css::uno::XWeak*>(this)); + + sal_uInt64 nAvailable; + eError = m_pFile->getPos(nAvailable); + if (eError != FileBase::E_None) + throw css::io::NotConnectedException(OUString(),static_cast<css::uno::XWeak*>(this)); + + nAvailable = nAvailable - nPos; + eError = m_pFile->setPos(osl_Pos_Absolut, nPos); + if (eError != FileBase::E_None) + throw css::io::NotConnectedException(OUString(),static_cast<css::uno::XWeak*>(this)); + return std::min<sal_Int64>(nAvailable, SAL_MAX_INT32); +} + + +void SAL_CALL OSLInputStreamWrapper::closeInput() +{ + if (!m_pFile) + throw css::io::NotConnectedException(OUString(), static_cast<css::uno::XWeak*>(this)); + + m_pFile->close(); + + m_pFile = nullptr; +} + +/*************************************************************************/ +// css::io::XOutputStream + + +OSLOutputStreamWrapper::OSLOutputStreamWrapper(osl::File & _rFile): + rFile(_rFile) +{} + +OSLOutputStreamWrapper::~OSLOutputStreamWrapper() {} + +void SAL_CALL OSLOutputStreamWrapper::writeBytes(const css::uno::Sequence< sal_Int8 >& aData) +{ + sal_uInt64 nWritten; + FileBase::RC eError = rFile.write(aData.getConstArray(),aData.getLength(), nWritten); + if (eError != FileBase::E_None + || nWritten != sal::static_int_cast< sal_uInt32 >(aData.getLength())) + { + throw css::io::BufferSizeExceededException(OUString(),static_cast<css::uno::XWeak*>(this)); + } +} + + +void SAL_CALL OSLOutputStreamWrapper::flush() +{ +} + + +void SAL_CALL OSLOutputStreamWrapper::closeOutput() +{ + rFile.close(); +} + +} // namespace comphelper + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/streaming/seekableinput.cxx b/comphelper/source/streaming/seekableinput.cxx new file mode 100644 index 000000000..3508f933e --- /dev/null +++ b/comphelper/source/streaming/seekableinput.cxx @@ -0,0 +1,233 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <com/sun/star/io/IOException.hpp> +#include <com/sun/star/io/NotConnectedException.hpp> +#include <com/sun/star/io/TempFile.hpp> +#include <com/sun/star/io/XOutputStream.hpp> + + +#include <comphelper/seekableinput.hxx> +#include <utility> + +using namespace ::com::sun::star; + +namespace comphelper +{ + +const sal_Int32 nConstBufferSize = 32000; + + +static void copyInputToOutput_Impl( const uno::Reference< io::XInputStream >& xIn, + const uno::Reference< io::XOutputStream >& xOut ) +{ + sal_Int32 nRead; + uno::Sequence< sal_Int8 > aSequence( nConstBufferSize ); + + do + { + nRead = xIn->readBytes( aSequence, nConstBufferSize ); + if ( nRead < nConstBufferSize ) + { + uno::Sequence< sal_Int8 > aTempBuf( aSequence.getConstArray(), nRead ); + xOut->writeBytes( aTempBuf ); + } + else + xOut->writeBytes( aSequence ); + } + while ( nRead == nConstBufferSize ); +} + + +OSeekableInputWrapper::OSeekableInputWrapper( + uno::Reference< io::XInputStream > xInStream, + uno::Reference< uno::XComponentContext > xContext ) +: m_xContext(std::move( xContext )) +, m_xOriginalStream(std::move( xInStream )) +{ + if ( !m_xContext.is() ) + throw uno::RuntimeException(); +} + + +OSeekableInputWrapper::~OSeekableInputWrapper() +{ +} + + +uno::Reference< io::XInputStream > OSeekableInputWrapper::CheckSeekableCanWrap( + const uno::Reference< io::XInputStream >& xInStream, + const uno::Reference< uno::XComponentContext >& rxContext ) +{ + // check that the stream is seekable and just wrap it if it is not + uno::Reference< io::XSeekable > xSeek( xInStream, uno::UNO_QUERY ); + if ( xSeek.is() ) + return xInStream; + + return new OSeekableInputWrapper(xInStream, rxContext); +} + + +void OSeekableInputWrapper::PrepareCopy_Impl() +{ + if ( !m_xCopyInput.is() ) + { + if ( !m_xContext.is() ) + throw uno::RuntimeException(); + + uno::Reference< io::XOutputStream > xTempOut( + io::TempFile::create(m_xContext), + uno::UNO_QUERY_THROW ); + + copyInputToOutput_Impl( m_xOriginalStream, xTempOut ); + xTempOut->closeOutput(); + + uno::Reference< io::XSeekable > xTempSeek( xTempOut, uno::UNO_QUERY ); + if ( xTempSeek.is() ) + { + xTempSeek->seek( 0 ); + m_xCopyInput.set( xTempOut, uno::UNO_QUERY ); + if ( m_xCopyInput.is() ) + m_xCopySeek = xTempSeek; + } + } + + if ( !m_xCopyInput.is() ) + throw io::IOException("no m_xCopyInput"); +} + +// XInputStream + +sal_Int32 SAL_CALL OSeekableInputWrapper::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( !m_xOriginalStream.is() ) + throw io::NotConnectedException(); + + PrepareCopy_Impl(); + + return m_xCopyInput->readBytes( aData, nBytesToRead ); +} + + +sal_Int32 SAL_CALL OSeekableInputWrapper::readSomeBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( !m_xOriginalStream.is() ) + throw io::NotConnectedException(); + + PrepareCopy_Impl(); + + return m_xCopyInput->readSomeBytes( aData, nMaxBytesToRead ); +} + + +void SAL_CALL OSeekableInputWrapper::skipBytes( sal_Int32 nBytesToSkip ) +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( !m_xOriginalStream.is() ) + throw io::NotConnectedException(); + + PrepareCopy_Impl(); + + m_xCopyInput->skipBytes( nBytesToSkip ); +} + + +sal_Int32 SAL_CALL OSeekableInputWrapper::available() +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( !m_xOriginalStream.is() ) + throw io::NotConnectedException(); + + PrepareCopy_Impl(); + + return m_xCopyInput->available(); +} + + +void SAL_CALL OSeekableInputWrapper::closeInput() +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( !m_xOriginalStream.is() ) + throw io::NotConnectedException(); + + m_xOriginalStream->closeInput(); + m_xOriginalStream.clear(); + + if ( m_xCopyInput.is() ) + { + m_xCopyInput->closeInput(); + m_xCopyInput.clear(); + } + + m_xCopySeek.clear(); +} + + +// XSeekable + +void SAL_CALL OSeekableInputWrapper::seek( sal_Int64 location ) +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( !m_xOriginalStream.is() ) + throw io::NotConnectedException(); + + PrepareCopy_Impl(); + + m_xCopySeek->seek( location ); +} + + +sal_Int64 SAL_CALL OSeekableInputWrapper::getPosition() +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( !m_xOriginalStream.is() ) + throw io::NotConnectedException(); + + PrepareCopy_Impl(); + + return m_xCopySeek->getPosition(); +} + + +sal_Int64 SAL_CALL OSeekableInputWrapper::getLength() +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( !m_xOriginalStream.is() ) + throw io::NotConnectedException(); + + PrepareCopy_Impl(); + + return m_xCopySeek->getLength(); +} + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/streaming/seqinputstreamserv.cxx b/comphelper/source/streaming/seqinputstreamserv.cxx new file mode 100644 index 000000000..5d10029a5 --- /dev/null +++ b/comphelper/source/streaming/seqinputstreamserv.cxx @@ -0,0 +1,215 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <comphelper/seqstream.hxx> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/io/NotConnectedException.hpp> +#include <com/sun/star/io/XSeekableInputStream.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/frame/DoubleInitializationException.hpp> +#include <mutex> + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace ::com::sun::star; + +namespace { + +class SequenceInputStreamService: + public ::cppu::WeakImplHelper< + lang::XServiceInfo, + io::XSeekableInputStream, + lang::XInitialization> +{ +public: + explicit SequenceInputStreamService(); + + // noncopyable + SequenceInputStreamService(const SequenceInputStreamService&) = delete; + const SequenceInputStreamService& operator=(const SequenceInputStreamService&) = delete; + + // css::lang::XServiceInfo: + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString & ServiceName ) override; + virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // css::io::XInputStream: + virtual ::sal_Int32 SAL_CALL readBytes( uno::Sequence< ::sal_Int8 > & aData, ::sal_Int32 nBytesToRead ) override; + virtual ::sal_Int32 SAL_CALL readSomeBytes( uno::Sequence< ::sal_Int8 > & aData, ::sal_Int32 nMaxBytesToRead ) override; + virtual void SAL_CALL skipBytes( ::sal_Int32 nBytesToSkip ) override; + virtual ::sal_Int32 SAL_CALL available() override; + virtual void SAL_CALL closeInput() override; + + // css::io::XSeekable: + virtual void SAL_CALL seek( ::sal_Int64 location ) override; + virtual ::sal_Int64 SAL_CALL getPosition() override; + virtual ::sal_Int64 SAL_CALL getLength() override; + + // css::lang::XInitialization: + virtual void SAL_CALL initialize( const uno::Sequence< css::uno::Any > & aArguments ) override; + +private: + virtual ~SequenceInputStreamService() override {} + + + std::mutex m_aMutex; + bool m_bInitialized; + uno::Reference< io::XInputStream > m_xInputStream; + uno::Reference< io::XSeekable > m_xSeekable; +}; + +SequenceInputStreamService::SequenceInputStreamService() +: m_bInitialized( false ) +{} + +// com.sun.star.uno.XServiceInfo: +OUString SAL_CALL SequenceInputStreamService::getImplementationName() +{ + return "com.sun.star.comp.SequenceInputStreamService"; +} + +sal_Bool SAL_CALL SequenceInputStreamService::supportsService( OUString const & serviceName ) +{ + return cppu::supportsService(this, serviceName); +} + +uno::Sequence< OUString > SAL_CALL SequenceInputStreamService::getSupportedServiceNames() +{ + return { "com.sun.star.io.SequenceInputStream" }; +} + +// css::io::XInputStream: +::sal_Int32 SAL_CALL SequenceInputStreamService::readBytes( uno::Sequence< ::sal_Int8 > & aData, ::sal_Int32 nBytesToRead ) +{ + std::scoped_lock aGuard( m_aMutex ); + if ( !m_xInputStream.is() ) + throw io::NotConnectedException(); + + return m_xInputStream->readBytes( aData, nBytesToRead ); +} + +::sal_Int32 SAL_CALL SequenceInputStreamService::readSomeBytes( uno::Sequence< ::sal_Int8 > & aData, ::sal_Int32 nMaxBytesToRead ) +{ + std::scoped_lock aGuard( m_aMutex ); + if ( !m_xInputStream.is() ) + throw io::NotConnectedException(); + + return m_xInputStream->readSomeBytes( aData, nMaxBytesToRead ); +} + +void SAL_CALL SequenceInputStreamService::skipBytes( ::sal_Int32 nBytesToSkip ) +{ + std::scoped_lock aGuard( m_aMutex ); + if ( !m_xInputStream.is() ) + throw io::NotConnectedException(); + + return m_xInputStream->skipBytes( nBytesToSkip ); +} + +::sal_Int32 SAL_CALL SequenceInputStreamService::available() +{ + std::scoped_lock aGuard( m_aMutex ); + if ( !m_xInputStream.is() ) + throw io::NotConnectedException(); + + return m_xInputStream->available(); +} + +void SAL_CALL SequenceInputStreamService::closeInput() +{ + std::scoped_lock aGuard( m_aMutex ); + if ( !m_xInputStream.is() ) + throw io::NotConnectedException(); + + m_xInputStream->closeInput(); + m_xInputStream.clear(); + m_xSeekable.clear(); +} + +// css::io::XSeekable: +void SAL_CALL SequenceInputStreamService::seek( ::sal_Int64 location ) +{ + std::scoped_lock aGuard( m_aMutex ); + if ( !m_xSeekable.is() ) + throw io::NotConnectedException(); + + m_xSeekable->seek( location ); +} + +::sal_Int64 SAL_CALL SequenceInputStreamService::getPosition() +{ + std::scoped_lock aGuard( m_aMutex ); + if ( !m_xSeekable.is() ) + throw io::NotConnectedException(); + + return m_xSeekable->getPosition(); +} + +::sal_Int64 SAL_CALL SequenceInputStreamService::getLength() +{ + std::scoped_lock aGuard( m_aMutex ); + if ( !m_xSeekable.is() ) + throw io::NotConnectedException(); + + return m_xSeekable->getLength(); +} + +// css::lang::XInitialization: +void SAL_CALL SequenceInputStreamService::initialize( const uno::Sequence< css::uno::Any > & aArguments ) +{ + std::scoped_lock aGuard( m_aMutex ); + if ( m_bInitialized ) + throw frame::DoubleInitializationException(); + + if ( aArguments.getLength() != 1 ) + throw lang::IllegalArgumentException( "Wrong number of arguments!", + static_cast< ::cppu::OWeakObject* >(this), + 1 ); + + uno::Sequence< sal_Int8 > aSeq; + if ( !(aArguments[0] >>= aSeq) ) + throw lang::IllegalArgumentException( "Unexpected type of argument!", + static_cast< ::cppu::OWeakObject* >(this), + 1 ); + + uno::Reference< io::XInputStream > xInputStream( + static_cast< ::cppu::OWeakObject* >( new ::comphelper::SequenceInputStream( aSeq ) ), + uno::UNO_QUERY_THROW ); + uno::Reference< io::XSeekable > xSeekable( xInputStream, uno::UNO_QUERY_THROW ); + m_xInputStream = xInputStream; + m_xSeekable = xSeekable; + m_bInitialized = true; +} + +} // anonymous namespace + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_SequenceInputStreamService( + css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new SequenceInputStreamService()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/streaming/seqoutputstreamserv.cxx b/comphelper/source/streaming/seqoutputstreamserv.cxx new file mode 100644 index 000000000..19ef79002 --- /dev/null +++ b/comphelper/source/streaming/seqoutputstreamserv.cxx @@ -0,0 +1,144 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <comphelper/seqstream.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/io/NotConnectedException.hpp> +#include <com/sun/star/io/XSequenceOutputStream.hpp> +#include <mutex> + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace ::com::sun::star; + + +namespace { + +class SequenceOutputStreamService: + public cppu::WeakImplHelper<lang::XServiceInfo, io::XSequenceOutputStream> +{ +public: + explicit SequenceOutputStreamService(); + + // noncopyable + SequenceOutputStreamService(const SequenceOutputStreamService&) = delete; + const SequenceOutputStreamService& operator=(const SequenceOutputStreamService&) = delete; + + // css::lang::XServiceInfo: + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString & ServiceName ) override; + virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // css::io::XOutputStream: + virtual void SAL_CALL writeBytes( const uno::Sequence< ::sal_Int8 > & aData ) override; + virtual void SAL_CALL flush() override; + virtual void SAL_CALL closeOutput() override; + + // css::io::XSequenceOutputStream: + virtual uno::Sequence< ::sal_Int8 > SAL_CALL getWrittenBytes( ) override; + +private: + virtual ~SequenceOutputStreamService() override {}; + + + std::mutex m_aMutex; + // WARNING: dtor of m_xOutputStream writes into m_aSequence so that must live longer! + uno::Sequence< ::sal_Int8 > m_aSequence; + uno::Reference< io::XOutputStream > m_xOutputStream; +}; +SequenceOutputStreamService::SequenceOutputStreamService() +{ + m_xOutputStream.set( static_cast < ::cppu::OWeakObject* >( new ::comphelper::OSequenceOutputStream( m_aSequence ) ), uno::UNO_QUERY_THROW ); +} + +// com.sun.star.uno.XServiceInfo: +OUString SAL_CALL SequenceOutputStreamService::getImplementationName() +{ + return "com.sun.star.comp.SequenceOutputStreamService"; +} + +sal_Bool SAL_CALL SequenceOutputStreamService::supportsService( OUString const & serviceName ) +{ + return cppu::supportsService(this, serviceName); +} + +uno::Sequence< OUString > SAL_CALL SequenceOutputStreamService::getSupportedServiceNames() +{ + return { "com.sun.star.io.SequenceOutputStream" }; +} + +// css::io::XOutputStream: +void SAL_CALL SequenceOutputStreamService::writeBytes( const uno::Sequence< ::sal_Int8 > & aData ) +{ + std::scoped_lock aGuard( m_aMutex ); + if ( !m_xOutputStream.is() ) + throw io::NotConnectedException(); + + m_xOutputStream->writeBytes( aData ); +} + +void SAL_CALL SequenceOutputStreamService::flush() +{ + std::scoped_lock aGuard( m_aMutex ); + if ( !m_xOutputStream.is() ) + throw io::NotConnectedException(); + + m_xOutputStream->flush(); +}; + +void SAL_CALL SequenceOutputStreamService::closeOutput() +{ + std::scoped_lock aGuard( m_aMutex ); + if ( !m_xOutputStream.is() ) + throw io::NotConnectedException(); + + m_xOutputStream->flush(); + m_xOutputStream->closeOutput(); + m_xOutputStream.clear(); +} + +// css::io::XSequenceOutputStream: +uno::Sequence< ::sal_Int8 > SAL_CALL SequenceOutputStreamService::getWrittenBytes() +{ + std::scoped_lock aGuard( m_aMutex ); + + if (m_xOutputStream.is()) + { + m_xOutputStream->flush(); + } + // else: no exception, just return the finished sequence + + return m_aSequence; +} + +} // anonymous namespace + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_SequenceOutputStreamService( + css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new SequenceOutputStreamService()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/streaming/seqstream.cxx b/comphelper/source/streaming/seqstream.cxx new file mode 100644 index 000000000..1f37a7967 --- /dev/null +++ b/comphelper/source/streaming/seqstream.cxx @@ -0,0 +1,247 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <com/sun/star/io/BufferSizeExceededException.hpp> +#include <com/sun/star/io/NotConnectedException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <comphelper/seqstream.hxx> + +#include <osl/diagnose.h> + +namespace comphelper +{ +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::uno; +using namespace ::osl; + + + + +SequenceInputStream::SequenceInputStream( + css::uno::Sequence<sal_Int8> const & rData) +: m_aData(rData) +, m_nPos(0) +{ +} + +// checks if closed, returns available size, not mutex-protected + +inline sal_Int32 SequenceInputStream::avail() +{ + if (m_nPos == -1) + throw NotConnectedException(OUString(), *this); + + return m_aData.getLength() - m_nPos; +} + +// css::io::XInputStream + +sal_Int32 SAL_CALL SequenceInputStream::readBytes( Sequence<sal_Int8>& aData, sal_Int32 nBytesToRead ) +{ + if (nBytesToRead < 0) + throw BufferSizeExceededException(OUString(),*this); + + std::scoped_lock aGuard( m_aMutex ); + + sal_Int32 nAvail = avail(); + + if (nAvail < nBytesToRead) + nBytesToRead = nAvail; + + aData.realloc(nBytesToRead); + memcpy(aData.getArray(), m_aData.getConstArray() + m_nPos, nBytesToRead); + m_nPos += nBytesToRead; + + return nBytesToRead; +} + +sal_Int32 SequenceInputStream::readSomeBytes( sal_Int8* pData, sal_Int32 nBytesToRead ) +{ + if (nBytesToRead < 0) + throw BufferSizeExceededException(OUString(),*this); + + std::scoped_lock aGuard( m_aMutex ); + + sal_Int32 nAvail = avail(); + + if (nAvail < nBytesToRead) + nBytesToRead = nAvail; + + memcpy(pData, m_aData.getConstArray() + m_nPos, nBytesToRead); + m_nPos += nBytesToRead; + + return nBytesToRead; +} + +sal_Int64 SAL_CALL SequenceInputStream::getSomething( const css::uno::Sequence< sal_Int8 >& rIdentifier ) +{ + if (rIdentifier == comphelper::ByteReader::getUnoTunnelId()) + return reinterpret_cast<sal_Int64>(static_cast<comphelper::ByteReader*>(this)); + return 0; +} + +sal_Int32 SAL_CALL SequenceInputStream::readSomeBytes( Sequence<sal_Int8>& aData, sal_Int32 nMaxBytesToRead ) +{ + // all data is available at once + return readBytes(aData, nMaxBytesToRead); +} + + +void SAL_CALL SequenceInputStream::skipBytes( sal_Int32 nBytesToSkip ) +{ + if (nBytesToSkip < 0) + throw BufferSizeExceededException(OUString(),*this); + + std::scoped_lock aGuard( m_aMutex ); + + sal_Int32 nAvail = avail(); + + if (nAvail < nBytesToSkip) + nBytesToSkip = nAvail; + + m_nPos += nBytesToSkip; +} + + +sal_Int32 SAL_CALL SequenceInputStream::available( ) +{ + std::scoped_lock aGuard( m_aMutex ); + + return avail(); +} + + +void SAL_CALL SequenceInputStream::closeInput( ) +{ + std::scoped_lock aGuard( m_aMutex ); + + if (m_nPos == -1) + throw NotConnectedException(OUString(), *this); + + m_nPos = -1; +} + +void SAL_CALL SequenceInputStream::seek( sal_Int64 location ) +{ + if ( location > m_aData.getLength() || location < 0 || location > SAL_MAX_INT32 ) + throw IllegalArgumentException("bad location", static_cast<cppu::OWeakObject*>(this), 1); + std::scoped_lock aGuard( m_aMutex ); + m_nPos = static_cast<sal_Int32>(location); +} + +sal_Int64 SAL_CALL SequenceInputStream::getPosition() +{ + std::scoped_lock aGuard( m_aMutex ); + return m_nPos; +} + +sal_Int64 SAL_CALL SequenceInputStream::getLength( ) +{ + std::scoped_lock aGuard( m_aMutex ); + return m_aData.getLength(); +} + + +OSequenceOutputStream::OSequenceOutputStream(Sequence< sal_Int8 >& _rSeq, double _nResizeFactor, sal_Int32 _nMinimumResize) + :m_rSequence(_rSeq) + ,m_nResizeFactor(_nResizeFactor) + ,m_nMinimumResize(_nMinimumResize) + ,m_nSize(0) // starting at position 0 + ,m_bConnected(true) +{ + OSL_ENSURE(m_nResizeFactor > 1, "OSequenceOutputStream::OSequenceOutputStream : invalid resize factor !"); + + if (m_nResizeFactor <= 1) + m_nResizeFactor = 1.3; +} + + +void SAL_CALL OSequenceOutputStream::writeBytes( const Sequence< sal_Int8 >& _rData ) +{ + std::scoped_lock aGuard(m_aMutex); + if (!m_bConnected) + throw NotConnectedException(); + + // ensure the sequence has enough space left + if (m_nSize + _rData.getLength() > m_rSequence.getLength()) + { + sal_Int32 nCurrentLength = m_rSequence.getLength(); + sal_Int32 nNewLength = static_cast< sal_Int32 >( + nCurrentLength * m_nResizeFactor); + + if (m_nMinimumResize > nNewLength - nCurrentLength) + // we have a minimum so it's not too inefficient for small sequences and small write requests + nNewLength = nCurrentLength + m_nMinimumResize; + + if (nNewLength < m_nSize + _rData.getLength()) + { // it's not enough... the data would not fit + + // let's take the double amount of the length of the data to be written, as the next write + // request could be as large as this one + sal_Int32 nNewGrowth = _rData.getLength() * 2; + nNewLength = nCurrentLength + nNewGrowth; + } + + // round it off to the next multiple of 4... + nNewLength = (nNewLength + 3) / 4 * 4; + + m_rSequence.realloc(nNewLength); + } + + OSL_ENSURE(m_rSequence.getLength() >= m_nSize + _rData.getLength(), + "ooops ... the realloc algorithm seems to be wrong :( !"); + + memcpy(m_rSequence.getArray() + m_nSize, _rData.getConstArray(), _rData.getLength()); + m_nSize += _rData.getLength(); +} + + +void SAL_CALL OSequenceOutputStream::flush( ) +{ + std::scoped_lock aGuard(m_aMutex); + if (!m_bConnected) + throw NotConnectedException(); + + // cut the sequence to the real size + m_rSequence.realloc(m_nSize); +} + +void OSequenceOutputStream::finalizeOutput() +{ + // cut the sequence to the real size + m_rSequence.realloc(m_nSize); + // and don't allow any further accesses + m_bConnected = false; +} + +void SAL_CALL OSequenceOutputStream::closeOutput() +{ + std::scoped_lock aGuard(m_aMutex); + if (!m_bConnected) + throw NotConnectedException(); + + finalizeOutput(); +} + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/streaming/streamsection.cxx b/comphelper/source/streaming/streamsection.cxx new file mode 100644 index 000000000..b03df8ab7 --- /dev/null +++ b/comphelper/source/streaming/streamsection.cxx @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <comphelper/streamsection.hxx> +#include <com/sun/star/io/XMarkableStream.hpp> +#include <com/sun/star/io/XDataInputStream.hpp> +#include <com/sun/star/io/XDataOutputStream.hpp> +#include <osl/diagnose.h> + +namespace comphelper +{ + + +OStreamSection::OStreamSection(const css::uno::Reference< css::io::XDataInputStream >& _rxInput) + :m_xMarkStream(_rxInput, css::uno::UNO_QUERY) + ,m_xInStream(_rxInput) + ,m_nBlockStart(-1) + ,m_nBlockLen(-1) +{ + OSL_ENSURE(m_xInStream.is() && m_xMarkStream.is(), "OStreamSection::OStreamSection : invalid argument !"); + if (m_xInStream.is() && m_xMarkStream.is()) + { + m_nBlockLen = _rxInput->readLong(); + m_nBlockStart = m_xMarkStream->createMark(); + } +} + + +OStreamSection::OStreamSection(const css::uno::Reference< css::io::XDataOutputStream >& _rxOutput) + :m_xMarkStream(_rxOutput, css::uno::UNO_QUERY) + ,m_xOutStream(_rxOutput) + ,m_nBlockStart(-1) + ,m_nBlockLen(-1) +{ + OSL_ENSURE(m_xOutStream.is() && m_xMarkStream.is(), "OStreamSection::OStreamSection : invalid argument !"); + if (m_xOutStream.is() && m_xMarkStream.is()) + { + m_nBlockStart = m_xMarkStream->createMark(); + m_nBlockLen = 0; + m_xOutStream->writeLong(m_nBlockLen); + } +} + + +OStreamSection::~OStreamSection() +{ + try + { // don't allow any exceptions to leave this block, this may be called during the stack unwinding of an exception + // handling routing + if (m_xInStream.is() && m_xMarkStream.is()) + { // we're working on an input stream + m_xMarkStream->jumpToMark(m_nBlockStart); + m_xInStream->skipBytes(m_nBlockLen); + m_xMarkStream->deleteMark(m_nBlockStart); + } + else if (m_xOutStream.is() && m_xMarkStream.is()) + { + sal_Int32 nRealBlockLength = m_xMarkStream->offsetToMark(m_nBlockStart) - sizeof(m_nBlockLen); + m_nBlockLen = nRealBlockLength; + m_xMarkStream->jumpToMark(m_nBlockStart); + m_xOutStream->writeLong(m_nBlockLen); + m_xMarkStream->jumpToFurthest(); + m_xMarkStream->deleteMark(m_nBlockStart); + } + } + catch(const css::uno::Exception&) + { + } +} + + +} // namespace comphelper + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |