android: Update app-specific/MIME type icons
[LibreOffice.git] / vcl / source / graphic / BinaryDataContainer.cxx
blob83cacb491ac22a60f455eb6cebe5c3b59dd97365
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 */
11 #include <vcl/BinaryDataContainer.hxx>
12 #include <o3tl/hash_combine.hxx>
13 #include <unotools/tempfile.hxx>
14 #include <comphelper/lok.hxx>
15 #include <comphelper/seqstream.hxx>
16 #include <sal/log.hxx>
18 struct BinaryDataContainer::Impl
20 // temp file to store the data out of RAM if necessary
21 std::unique_ptr<utl::TempFileNamed> mpFile;
22 // the binary data
23 std::shared_ptr<std::vector<sal_uInt8>> mpData;
25 Impl(SvStream& stream, size_t size) { readData(stream, size); }
27 /// Populate mpData from the stream
28 void readData(SvStream& stream, size_t size)
30 auto pData = std::make_shared<std::vector<sal_uInt8>>(size);
31 if (stream.ReadBytes(pData->data(), pData->size()) == size)
32 mpData = std::move(pData);
35 /// ensure the data is in-RAM
36 void ensureSwappedIn()
38 if (mpData || !mpFile)
39 return;
41 auto pStream = mpFile->GetStream(StreamMode::READ);
42 pStream->Seek(0);
43 readData(*pStream, pStream->remainingSize());
45 // Horrifying data loss ...
46 SAL_WARN_IF(pStream->GetError(), "vcl",
47 "Inconsistent system - failed to swap image back in");
48 SAL_DEBUG("Swap in: " << pStream->GetError());
51 void swapOut()
53 if (mpFile)
55 // we already have it swapped out.
56 mpData.reset();
57 return;
60 if (!mpData || mpData->empty())
61 return;
63 mpFile.reset(new utl::TempFileNamed());
64 auto pStream = mpFile->GetStream(StreamMode::READWRITE);
66 pStream->WriteBytes(mpData->data(), mpData->size());
68 mpData.reset();
72 BinaryDataContainer::BinaryDataContainer(SvStream& stream, size_t size)
73 : mpImpl(new Impl(stream, size))
77 size_t BinaryDataContainer::calculateHash() const
79 size_t nSeed = 0;
80 if (mpImpl && mpImpl->mpData && !mpImpl->mpData->empty())
82 o3tl::hash_combine(nSeed, getSize());
83 for (sal_uInt8 const& rByte : *mpImpl->mpData)
84 o3tl::hash_combine(nSeed, rByte);
86 return nSeed;
89 css::uno::Sequence<sal_Int8> BinaryDataContainer::getCopyAsByteSequence() const
91 if (isEmpty())
92 return css::uno::Sequence<sal_Int8>();
93 assert(mpImpl);
95 css::uno::Sequence<sal_Int8> aData(getSize());
97 std::copy(mpImpl->mpData->cbegin(), mpImpl->mpData->cend(), aData.getArray());
99 return aData;
102 namespace
105 * Hold a reference on the internal state in case we swap out
106 * and free the vector while someone holds an SvStream pointer.
108 class ReferencedMemoryStream : public SvMemoryStream
110 std::shared_ptr<std::vector<sal_uInt8>> mpData;
112 public:
113 ReferencedMemoryStream(const std::shared_ptr<std::vector<sal_uInt8>>& pData)
114 : SvMemoryStream(pData->data(), pData->size(), StreamMode::READ)
115 , mpData(pData)
120 class ReferencedXInputStream : public comphelper::MemoryInputStream
122 std::shared_ptr<std::vector<sal_uInt8>> mpData;
124 public:
125 ReferencedXInputStream(const std::shared_ptr<std::vector<sal_uInt8>>& pData)
126 : comphelper::MemoryInputStream(reinterpret_cast<const sal_Int8*>(pData->data()),
127 pData->size())
128 , mpData(pData)
134 std::shared_ptr<SvStream> BinaryDataContainer::getAsStream()
136 ensureSwappedIn(); // TODO: transfer in streamed chunks
137 return std::make_shared<ReferencedMemoryStream>(mpImpl->mpData);
140 css::uno::Reference<css::io::XInputStream> BinaryDataContainer::getAsXInputStream()
142 ensureSwappedIn(); // TODO: transfer in streamed chunks
143 return new ReferencedXInputStream(mpImpl->mpData);
146 std::size_t BinaryDataContainer::writeToStream(SvStream& rStream) const
148 ensureSwappedIn(); // TODO: transfer in streamed chunks
149 return rStream.WriteBytes(getData(), getSize());
152 size_t BinaryDataContainer::getSize() const
154 ensureSwappedIn();
155 return mpImpl && mpImpl->mpData ? mpImpl->mpData->size() : 0;
158 size_t BinaryDataContainer::getSizeBytes() const
160 return mpImpl && mpImpl->mpData ? mpImpl->mpData->size() : 0;
163 bool BinaryDataContainer::isEmpty() const
165 ensureSwappedIn();
166 return !mpImpl || !mpImpl->mpData || mpImpl->mpData->empty();
169 const sal_uInt8* BinaryDataContainer::getData() const
171 ensureSwappedIn();
172 return mpImpl && mpImpl->mpData ? mpImpl->mpData->data() : nullptr;
175 void BinaryDataContainer::ensureSwappedIn() const
177 if (mpImpl)
178 mpImpl->ensureSwappedIn();
181 void BinaryDataContainer::swapOut() const
183 // Only bother reducing memory footprint in kit mode - for mobile/online etc.
184 if (!mpImpl || !comphelper::LibreOfficeKit::isActive())
185 return;
187 mpImpl->swapOut();
190 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */