summaryrefslogtreecommitdiffstats
path: root/vcl/source/graphic/BinaryDataContainer.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /vcl/source/graphic/BinaryDataContainer.cxx
parentInitial commit. (diff)
downloadlibreoffice-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.cxx189
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: */