LibreOffice Module comphelper (master) 1
seqstream.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 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21
22#include <com/sun/star/io/BufferSizeExceededException.hpp>
23#include <com/sun/star/io/NotConnectedException.hpp>
24#include <com/sun/star/lang/IllegalArgumentException.hpp>
26
27#include <osl/diagnose.h>
28
29namespace comphelper
30{
31using namespace ::com::sun::star::lang;
32using namespace ::com::sun::star::io;
33using namespace ::com::sun::star::uno;
34using namespace ::osl;
35
36
37
38
40 css::uno::Sequence<sal_Int8> const & rData)
42, m_nPos(0)
43{
44}
45
46// checks if closed, returns available size, not mutex-protected
47
49{
50 if (m_nPos == -1)
51 throw NotConnectedException(OUString(), *this);
52
53 return m_aData.getLength() - m_nPos;
54}
55
56// css::io::XInputStream
57
58sal_Int32 SAL_CALL SequenceInputStream::readBytes( Sequence<sal_Int8>& aData, sal_Int32 nBytesToRead )
59{
60 if (nBytesToRead < 0)
61 throw BufferSizeExceededException(OUString(),*this);
62
63 std::scoped_lock aGuard( m_aMutex );
64
65 sal_Int32 nAvail = avail();
66
67 if (nAvail < nBytesToRead)
68 nBytesToRead = nAvail;
69
70 aData.realloc(nBytesToRead);
71 memcpy(aData.getArray(), m_aData.getConstArray() + m_nPos, nBytesToRead);
72 m_nPos += nBytesToRead;
73
74 return nBytesToRead;
75}
76
77sal_Int32 SequenceInputStream::readSomeBytes( sal_Int8* pData, sal_Int32 nBytesToRead )
78{
79 if (nBytesToRead < 0)
80 throw BufferSizeExceededException(OUString(),*this);
81
82 std::scoped_lock aGuard( m_aMutex );
83
84 sal_Int32 nAvail = avail();
85
86 if (nAvail < nBytesToRead)
87 nBytesToRead = nAvail;
88
89 memcpy(pData, m_aData.getConstArray() + m_nPos, nBytesToRead);
90 m_nPos += nBytesToRead;
91
92 return nBytesToRead;
93}
94
95sal_Int64 SAL_CALL SequenceInputStream::getSomething( const css::uno::Sequence< sal_Int8 >& rIdentifier )
96{
97 if (rIdentifier == comphelper::ByteReader::getUnoTunnelId())
98 return reinterpret_cast<sal_Int64>(static_cast<comphelper::ByteReader*>(this));
99 return 0;
100}
101
102sal_Int32 SAL_CALL SequenceInputStream::readSomeBytes( Sequence<sal_Int8>& aData, sal_Int32 nMaxBytesToRead )
103{
104 // all data is available at once
105 return readBytes(aData, nMaxBytesToRead);
106}
107
108
109void SAL_CALL SequenceInputStream::skipBytes( sal_Int32 nBytesToSkip )
110{
111 if (nBytesToSkip < 0)
112 throw BufferSizeExceededException(OUString(),*this);
113
114 std::scoped_lock aGuard( m_aMutex );
115
116 sal_Int32 nAvail = avail();
117
118 if (nAvail < nBytesToSkip)
119 nBytesToSkip = nAvail;
120
121 m_nPos += nBytesToSkip;
122}
123
124
126{
127 std::scoped_lock aGuard( m_aMutex );
128
129 return avail();
130}
131
132
134{
135 std::scoped_lock aGuard( m_aMutex );
136
137 if (m_nPos == -1)
138 throw NotConnectedException(OUString(), *this);
139
140 m_nPos = -1;
141}
142
143void SAL_CALL SequenceInputStream::seek( sal_Int64 location )
144{
145 if ( location > m_aData.getLength() || location < 0 || location > SAL_MAX_INT32 )
146 throw IllegalArgumentException("bad location", static_cast<cppu::OWeakObject*>(this), 1);
147 std::scoped_lock aGuard( m_aMutex );
148 m_nPos = static_cast<sal_Int32>(location);
149}
150
152{
153 std::scoped_lock aGuard( m_aMutex );
154 return m_nPos;
155}
156
158{
159 std::scoped_lock aGuard( m_aMutex );
160 return m_aData.getLength();
161}
162
163
164OSequenceOutputStream::OSequenceOutputStream(Sequence< sal_Int8 >& _rSeq, double _nResizeFactor, sal_Int32 _nMinimumResize)
165 :m_rSequence(_rSeq)
166 ,m_nResizeFactor(_nResizeFactor)
167 ,m_nMinimumResize(_nMinimumResize)
168 ,m_nSize(0) // starting at position 0
169 ,m_bConnected(true)
170{
171 OSL_ENSURE(m_nResizeFactor > 1, "OSequenceOutputStream::OSequenceOutputStream : invalid resize factor !");
172
173 if (m_nResizeFactor <= 1)
174 m_nResizeFactor = 1.3;
175}
176
177
178void SAL_CALL OSequenceOutputStream::writeBytes( const Sequence< sal_Int8 >& _rData )
179{
180 std::scoped_lock aGuard(m_aMutex);
181 if (!m_bConnected)
182 throw NotConnectedException();
183
184 // ensure the sequence has enough space left
185 if (m_nSize + _rData.getLength() > m_rSequence.getLength())
186 {
187 sal_Int32 nCurrentLength = m_rSequence.getLength();
188 sal_Int32 nNewLength = static_cast< sal_Int32 >(
189 nCurrentLength * m_nResizeFactor);
190
191 if (m_nMinimumResize > nNewLength - nCurrentLength)
192 // we have a minimum so it's not too inefficient for small sequences and small write requests
193 nNewLength = nCurrentLength + m_nMinimumResize;
194
195 if (nNewLength < m_nSize + _rData.getLength())
196 { // it's not enough... the data would not fit
197
198 // let's take the double amount of the length of the data to be written, as the next write
199 // request could be as large as this one
200 sal_Int32 nNewGrowth = _rData.getLength() * 2;
201 nNewLength = nCurrentLength + nNewGrowth;
202 }
203
204 // round it off to the next multiple of 4...
205 nNewLength = (nNewLength + 3) / 4 * 4;
206
207 m_rSequence.realloc(nNewLength);
208 }
209
210 OSL_ENSURE(m_rSequence.getLength() >= m_nSize + _rData.getLength(),
211 "ooops ... the realloc algorithm seems to be wrong :( !");
212
213 memcpy(m_rSequence.getArray() + m_nSize, _rData.getConstArray(), _rData.getLength());
214 m_nSize += _rData.getLength();
215}
216
217
218void SAL_CALL OSequenceOutputStream::flush( )
219{
220 std::scoped_lock aGuard(m_aMutex);
221 if (!m_bConnected)
222 throw NotConnectedException();
223
224 // cut the sequence to the real size
225 m_rSequence.realloc(m_nSize);
226}
227
228void OSequenceOutputStream::finalizeOutput()
229{
230 // cut the sequence to the real size
231 m_rSequence.realloc(m_nSize);
232 // and don't allow any further accesses
233 m_bConnected = false;
234}
235
236void SAL_CALL OSequenceOutputStream::closeOutput()
237{
238 std::scoped_lock aGuard(m_aMutex);
239 if (!m_bConnected)
240 throw NotConnectedException();
241
242 finalizeOutput();
243}
244
245} // namespace comphelper
246
247/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Interface that we can cast to, to bypass the inefficiency of using Sequence<sal_Int8> when reading vi...
Definition: bytereader.hxx:21
static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId()
Definition: basicio.cxx:164
virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) override
Definition: seqstream.cxx:109
virtual sal_Int64 SAL_CALL getPosition() override
Definition: seqstream.cxx:151
virtual sal_Int64 SAL_CALL getLength() override
Definition: seqstream.cxx:157
virtual sal_Int32 SAL_CALL available() override
Definition: seqstream.cxx:125
css::uno::Sequence< sal_Int8 > const m_aData
Definition: seqstream.hxx:46
SequenceInputStream(css::uno::Sequence< sal_Int8 > const &rData)
Definition: seqstream.cxx:39
virtual void SAL_CALL closeInput() override
Definition: seqstream.cxx:133
virtual sal_Int32 SAL_CALL readSomeBytes(css::uno::Sequence< sal_Int8 > &aData, sal_Int32 nMaxBytesToRead) override
virtual void SAL_CALL seek(sal_Int64 location) override
Definition: seqstream.cxx:143
virtual sal_Int64 SAL_CALL getSomething(const css::uno::Sequence< sal_Int8 > &aIdentifier) override
Definition: seqstream.cxx:95
virtual sal_Int32 SAL_CALL readBytes(css::uno::Sequence< sal_Int8 > &aData, sal_Int32 nBytesToRead) override
MapData m_aData
::osl::Mutex m_aMutex
size_t m_nPos
sal_uInt32 m_nSize
std::unique_ptr< sal_Int32[]> pData
const ContentProperties & rData
constexpr OUStringLiteral aData
#define SAL_MAX_INT32
signed char sal_Int8