1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
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
;
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
)
41 auto pStream
= mpFile
->GetStream(StreamMode::READ
);
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());
55 // we already have it swapped out.
60 if (!mpData
|| mpData
->empty())
63 mpFile
.reset(new utl::TempFileNamed());
64 auto pStream
= mpFile
->GetStream(StreamMode::READWRITE
);
66 pStream
->WriteBytes(mpData
->data(), mpData
->size());
72 BinaryDataContainer::BinaryDataContainer(SvStream
& stream
, size_t size
)
73 : mpImpl(new Impl(stream
, size
))
77 size_t BinaryDataContainer::calculateHash() const
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
);
89 css::uno::Sequence
<sal_Int8
> BinaryDataContainer::getCopyAsByteSequence() const
92 return css::uno::Sequence
<sal_Int8
>();
95 css::uno::Sequence
<sal_Int8
> aData(getSize());
97 std::copy(mpImpl
->mpData
->cbegin(), mpImpl
->mpData
->cend(), aData
.getArray());
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
;
113 ReferencedMemoryStream(const std::shared_ptr
<std::vector
<sal_uInt8
>>& pData
)
114 : SvMemoryStream(pData
->data(), pData
->size(), StreamMode::READ
)
120 class ReferencedXInputStream
: public comphelper::MemoryInputStream
122 std::shared_ptr
<std::vector
<sal_uInt8
>> mpData
;
125 ReferencedXInputStream(const std::shared_ptr
<std::vector
<sal_uInt8
>>& pData
)
126 : comphelper::MemoryInputStream(reinterpret_cast<const sal_Int8
*>(pData
->data()),
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
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
166 return !mpImpl
|| !mpImpl
->mpData
|| mpImpl
->mpData
->empty();
169 const sal_uInt8
* BinaryDataContainer::getData() const
172 return mpImpl
&& mpImpl
->mpData
? mpImpl
->mpData
->data() : nullptr;
175 void BinaryDataContainer::ensureSwappedIn() const
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())
190 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */