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>
20 struct BinaryDataContainer::Impl
22 // temp file to store the data out of RAM if necessary
23 std::unique_ptr
<utl::TempFileFast
> mpFile
;
25 std::shared_ptr
<std::vector
<sal_uInt8
>> mpData
;
27 Impl(SvStream
& stream
, size_t size
) { readData(stream
, size
); }
29 /// Populate mpData from the stream
30 void readData(SvStream
& stream
, size_t size
)
32 auto pData
= std::make_shared
<std::vector
<sal_uInt8
>>(size
);
33 if (stream
.ReadBytes(pData
->data(), pData
->size()) == size
)
34 mpData
= std::move(pData
);
37 /// ensure the data is in-RAM
38 void ensureSwappedIn()
40 if (mpData
|| !mpFile
)
43 auto pStream
= mpFile
->GetStream(StreamMode::READ
);
45 readData(*pStream
, pStream
->remainingSize());
47 // Horrifying data loss ...
48 SAL_WARN_IF(pStream
->GetError(), "vcl",
49 "Inconsistent system - failed to swap image back in");
56 // we already have it swapped out.
61 if (!mpData
|| mpData
->empty())
64 mpFile
.reset(new utl::TempFileFast());
65 auto pStream
= mpFile
->GetStream(StreamMode::READWRITE
);
67 pStream
->WriteBytes(mpData
->data(), mpData
->size());
73 BinaryDataContainer::BinaryDataContainer(SvStream
& stream
, size_t size
)
74 : mpImpl(new Impl(stream
, size
))
78 size_t BinaryDataContainer::calculateHash() const
81 if (mpImpl
&& mpImpl
->mpData
&& !mpImpl
->mpData
->empty())
83 o3tl::hash_combine(nSeed
, getSize());
84 for (sal_uInt8
const& rByte
: *mpImpl
->mpData
)
85 o3tl::hash_combine(nSeed
, rByte
);
90 css::uno::Sequence
<sal_Int8
> BinaryDataContainer::getCopyAsByteSequence() const
93 return css::uno::Sequence
<sal_Int8
>();
96 css::uno::Sequence
<sal_Int8
> aData(getSize());
98 std::copy(mpImpl
->mpData
->cbegin(), mpImpl
->mpData
->cend(), aData
.getArray());
106 * Hold a reference on the internal state in case we swap out
107 * and free the vector while someone holds an SvStream pointer.
109 class ReferencedMemoryStream
: public SvMemoryStream
111 std::shared_ptr
<std::vector
<sal_uInt8
>> mpData
;
114 ReferencedMemoryStream(const std::shared_ptr
<std::vector
<sal_uInt8
>>& pData
)
115 : SvMemoryStream(pData
->data(), pData
->size(), StreamMode::READ
)
121 class ReferencedXInputStream
: public comphelper::MemoryInputStream
123 std::shared_ptr
<std::vector
<sal_uInt8
>> mpData
;
126 ReferencedXInputStream(const std::shared_ptr
<std::vector
<sal_uInt8
>>& pData
)
127 : comphelper::MemoryInputStream(reinterpret_cast<const sal_Int8
*>(pData
->data()),
135 std::shared_ptr
<SvStream
> BinaryDataContainer::getAsStream()
137 ensureSwappedIn(); // TODO: transfer in streamed chunks
138 return std::make_shared
<ReferencedMemoryStream
>(mpImpl
->mpData
);
141 css::uno::Reference
<css::io::XInputStream
> BinaryDataContainer::getAsXInputStream()
143 ensureSwappedIn(); // TODO: transfer in streamed chunks
144 return new ReferencedXInputStream(mpImpl
->mpData
);
147 std::size_t BinaryDataContainer::writeToStream(SvStream
& rStream
) const
149 ensureSwappedIn(); // TODO: transfer in streamed chunks
150 return rStream
.WriteBytes(getData(), getSize());
153 size_t BinaryDataContainer::getSize() const
156 return mpImpl
&& mpImpl
->mpData
? mpImpl
->mpData
->size() : 0;
159 size_t BinaryDataContainer::getSizeBytes() const
161 return mpImpl
&& mpImpl
->mpData
? mpImpl
->mpData
->size() : 0;
164 bool BinaryDataContainer::isEmpty() const
167 return !mpImpl
|| !mpImpl
->mpData
|| mpImpl
->mpData
->empty();
170 const sal_uInt8
* BinaryDataContainer::getData() const
173 return mpImpl
&& mpImpl
->mpData
? mpImpl
->mpData
->data() : nullptr;
176 void BinaryDataContainer::ensureSwappedIn() const
179 mpImpl
->ensureSwappedIn();
182 void BinaryDataContainer::swapOut() const
184 // Only bother reducing memory footprint in kit mode - for mobile/online etc.
185 if (!mpImpl
|| !comphelper::LibreOfficeKit::isActive())
191 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */