LibreOffice Module vcl (master) 1
BinaryDataContainer.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 */
10
12#include <o3tl/hash_combine.hxx>
13#include <unotools/tempfile.hxx>
14#include <comphelper/lok.hxx>
16#include <sal/log.hxx>
17
19{
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;
24
25 Impl(SvStream& stream, size_t size) { readData(stream, size); }
26
28 void readData(SvStream& stream, size_t size)
29 {
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);
33 }
34
37 {
38 if (mpData || !mpFile)
39 return;
40
41 auto pStream = mpFile->GetStream(StreamMode::READ);
42 pStream->Seek(0);
43 readData(*pStream, pStream->remainingSize());
44
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());
49 }
50
51 void swapOut()
52 {
53 if (mpFile)
54 {
55 // we already have it swapped out.
56 mpData.reset();
57 return;
58 }
59
60 if (!mpData || mpData->empty())
61 return;
62
63 mpFile.reset(new utl::TempFileNamed());
64 auto pStream = mpFile->GetStream(StreamMode::READWRITE);
65
66 pStream->WriteBytes(mpData->data(), mpData->size());
67
68 mpData.reset();
69 }
70};
71
73 : mpImpl(new Impl(stream, size))
74{
75}
76
78{
79 size_t nSeed = 0;
80 if (mpImpl && mpImpl->mpData && !mpImpl->mpData->empty())
81 {
83 for (sal_uInt8 const& rByte : *mpImpl->mpData)
84 o3tl::hash_combine(nSeed, rByte);
85 }
86 return nSeed;
87}
88
89css::uno::Sequence<sal_Int8> BinaryDataContainer::getCopyAsByteSequence() const
90{
91 if (isEmpty())
92 return css::uno::Sequence<sal_Int8>();
93 assert(mpImpl);
94
95 css::uno::Sequence<sal_Int8> aData(getSize());
96
97 std::copy(mpImpl->mpData->cbegin(), mpImpl->mpData->cend(), aData.getArray());
98
99 return aData;
100}
101
102namespace
103{
104/*
105 * Hold a reference on the internal state in case we swap out
106 * and free the vector while someone holds an SvStream pointer.
107 */
108class ReferencedMemoryStream : public SvMemoryStream
109{
110 std::shared_ptr<std::vector<sal_uInt8>> mpData;
111
112public:
113 ReferencedMemoryStream(const std::shared_ptr<std::vector<sal_uInt8>>& pData)
115 , mpData(pData)
116 {
117 }
118};
119
120class ReferencedXInputStream : public comphelper::MemoryInputStream
121{
122 std::shared_ptr<std::vector<sal_uInt8>> mpData;
123
124public:
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)
129 {
130 }
131};
132}
133
134std::shared_ptr<SvStream> BinaryDataContainer::getAsStream()
135{
136 ensureSwappedIn(); // TODO: transfer in streamed chunks
137 return std::make_shared<ReferencedMemoryStream>(mpImpl->mpData);
138}
139
140css::uno::Reference<css::io::XInputStream> BinaryDataContainer::getAsXInputStream()
141{
142 ensureSwappedIn(); // TODO: transfer in streamed chunks
143 return new ReferencedXInputStream(mpImpl->mpData);
144}
145
147{
148 ensureSwappedIn(); // TODO: transfer in streamed chunks
149 return rStream.WriteBytes(getData(), getSize());
150}
151
153{
155 return mpImpl && mpImpl->mpData ? mpImpl->mpData->size() : 0;
156}
157
159{
160 return mpImpl && mpImpl->mpData ? mpImpl->mpData->size() : 0;
161}
162
164{
166 return !mpImpl || !mpImpl->mpData || mpImpl->mpData->empty();
167}
168
170{
172 return mpImpl && mpImpl->mpData ? mpImpl->mpData->data() : nullptr;
173}
174
176{
177 if (mpImpl)
178 mpImpl->ensureSwappedIn();
179}
180
182{
183 // Only bother reducing memory footprint in kit mode - for mobile/online etc.
185 return;
186
187 mpImpl->swapOut();
188}
189
190/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::size_t getSizeBytes() const
return the in-memory size in bytes as of now.
css::uno::Sequence< sal_Int8 > getCopyAsByteSequence() const
BinaryDataContainer()=default
css::uno::Reference< css::io::XInputStream > getAsXInputStream()
std::shared_ptr< Impl > mpImpl
std::size_t writeToStream(SvStream &rStream) const
writes the contents to the given stream
size_t calculateHash() const
void swapOut() const
swap out to disk for now
std::shared_ptr< SvStream > getAsStream()
const sal_uInt8 * getData() const
std::size_t WriteBytes(const void *pData, std::size_t nSize)
Reference< XOutputStream > stream
#define SAL_WARN_IF(condition, area, stream)
#define SAL_DEBUG(stream)
std::unique_ptr< sal_Int32[]> pData
constexpr OUStringLiteral aData
size
std::enable_if_t<(sizeof(N)==4)> hash_combine(N &nSeed, T const *pValue, size_t nCount)
READ
StreamMode
void ensureSwappedIn()
ensure the data is in-RAM
std::unique_ptr< utl::TempFileNamed > mpFile
void readData(SvStream &stream, size_t size)
Populate mpData from the stream.
std::shared_ptr< std::vector< sal_uInt8 > > mpData
Impl(SvStream &stream, size_t size)
unsigned char sal_uInt8
signed char sal_Int8