diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /vcl/source/graphic/BinaryDataContainer.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip |
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vcl/source/graphic/BinaryDataContainer.cxx')
-rw-r--r-- | vcl/source/graphic/BinaryDataContainer.cxx | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/vcl/source/graphic/BinaryDataContainer.cxx b/vcl/source/graphic/BinaryDataContainer.cxx new file mode 100644 index 0000000000..89ae5eb8da --- /dev/null +++ b/vcl/source/graphic/BinaryDataContainer.cxx @@ -0,0 +1,189 @@ +/* -*- 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/. + * + */ + +#include <vcl/BinaryDataContainer.hxx> +#include <o3tl/hash_combine.hxx> +#include <unotools/tempfile.hxx> +#include <comphelper/lok.hxx> +#include <comphelper/seqstream.hxx> +#include <sal/log.hxx> + +struct BinaryDataContainer::Impl +{ + // temp file to store the data out of RAM if necessary + std::unique_ptr<utl::TempFileFast> mpFile; + // the binary data + std::shared_ptr<std::vector<sal_uInt8>> mpData; + + Impl(SvStream& stream, size_t size) { readData(stream, size); } + + /// Populate mpData from the stream + void readData(SvStream& stream, size_t size) + { + auto pData = std::make_shared<std::vector<sal_uInt8>>(size); + if (stream.ReadBytes(pData->data(), pData->size()) == size) + mpData = std::move(pData); + } + + /// ensure the data is in-RAM + void ensureSwappedIn() + { + if (mpData || !mpFile) + return; + + auto pStream = mpFile->GetStream(StreamMode::READ); + pStream->Seek(0); + readData(*pStream, pStream->remainingSize()); + + // Horrifying data loss ... + SAL_WARN_IF(pStream->GetError(), "vcl", + "Inconsistent system - failed to swap image back in"); + } + + void swapOut() + { + if (mpFile) + { + // we already have it swapped out. + mpData.reset(); + return; + } + + if (!mpData || mpData->empty()) + return; + + mpFile.reset(new utl::TempFileFast()); + auto pStream = mpFile->GetStream(StreamMode::READWRITE); + + pStream->WriteBytes(mpData->data(), mpData->size()); + + mpData.reset(); + } +}; + +BinaryDataContainer::BinaryDataContainer(SvStream& stream, size_t size) + : mpImpl(new Impl(stream, size)) +{ +} + +size_t BinaryDataContainer::calculateHash() const +{ + size_t nSeed = 0; + if (mpImpl && mpImpl->mpData && !mpImpl->mpData->empty()) + { + o3tl::hash_combine(nSeed, getSize()); + for (sal_uInt8 const& rByte : *mpImpl->mpData) + o3tl::hash_combine(nSeed, rByte); + } + return nSeed; +} + +css::uno::Sequence<sal_Int8> BinaryDataContainer::getCopyAsByteSequence() const +{ + if (isEmpty()) + return css::uno::Sequence<sal_Int8>(); + assert(mpImpl); + + css::uno::Sequence<sal_Int8> aData(getSize()); + + std::copy(mpImpl->mpData->cbegin(), mpImpl->mpData->cend(), aData.getArray()); + + return aData; +} + +namespace +{ +/* + * Hold a reference on the internal state in case we swap out + * and free the vector while someone holds an SvStream pointer. + */ +class ReferencedMemoryStream : public SvMemoryStream +{ + std::shared_ptr<std::vector<sal_uInt8>> mpData; + +public: + ReferencedMemoryStream(const std::shared_ptr<std::vector<sal_uInt8>>& pData) + : SvMemoryStream(pData->data(), pData->size(), StreamMode::READ) + , mpData(pData) + { + } +}; + +class ReferencedXInputStream : public comphelper::MemoryInputStream +{ + std::shared_ptr<std::vector<sal_uInt8>> mpData; + +public: + ReferencedXInputStream(const std::shared_ptr<std::vector<sal_uInt8>>& pData) + : comphelper::MemoryInputStream(reinterpret_cast<const sal_Int8*>(pData->data()), + pData->size()) + , mpData(pData) + { + } +}; +} + +std::shared_ptr<SvStream> BinaryDataContainer::getAsStream() +{ + ensureSwappedIn(); // TODO: transfer in streamed chunks + return std::make_shared<ReferencedMemoryStream>(mpImpl->mpData); +} + +css::uno::Reference<css::io::XInputStream> BinaryDataContainer::getAsXInputStream() +{ + ensureSwappedIn(); // TODO: transfer in streamed chunks + return new ReferencedXInputStream(mpImpl->mpData); +} + +std::size_t BinaryDataContainer::writeToStream(SvStream& rStream) const +{ + ensureSwappedIn(); // TODO: transfer in streamed chunks + return rStream.WriteBytes(getData(), getSize()); +} + +size_t BinaryDataContainer::getSize() const +{ + ensureSwappedIn(); + return mpImpl && mpImpl->mpData ? mpImpl->mpData->size() : 0; +} + +size_t BinaryDataContainer::getSizeBytes() const +{ + return mpImpl && mpImpl->mpData ? mpImpl->mpData->size() : 0; +} + +bool BinaryDataContainer::isEmpty() const +{ + ensureSwappedIn(); + return !mpImpl || !mpImpl->mpData || mpImpl->mpData->empty(); +} + +const sal_uInt8* BinaryDataContainer::getData() const +{ + ensureSwappedIn(); + return mpImpl && mpImpl->mpData ? mpImpl->mpData->data() : nullptr; +} + +void BinaryDataContainer::ensureSwappedIn() const +{ + if (mpImpl) + mpImpl->ensureSwappedIn(); +} + +void BinaryDataContainer::swapOut() const +{ + // Only bother reducing memory footprint in kit mode - for mobile/online etc. + if (!mpImpl || !comphelper::LibreOfficeKit::isActive()) + return; + + mpImpl->swapOut(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |