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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <com/sun/star/io/BufferSizeExceededException.hpp>
23 #include <com/sun/star/io/NotConnectedException.hpp>
24 #include <com/sun/star/lang/IllegalArgumentException.hpp>
25 #include <comphelper/seqstream.hxx>
27 #include <osl/diagnose.h>
31 using namespace ::com::sun::star::lang
;
32 using namespace ::com::sun::star::io
;
33 using namespace ::com::sun::star::uno
;
38 MemoryInputStream::MemoryInputStream(
39 const sal_Int8
* pData
, sal_Int32 nDataLength
)
40 : m_pMemoryData(pData
)
41 , m_nMemoryDataLength(nDataLength
)
46 // checks if closed, returns available size, not mutex-protected
48 inline sal_Int32
MemoryInputStream::avail()
51 throw NotConnectedException(OUString(), *this);
53 return m_nMemoryDataLength
- m_nPos
;
56 // css::io::XInputStream
58 sal_Int32 SAL_CALL
MemoryInputStream::readBytes( Sequence
<sal_Int8
>& aData
, sal_Int32 nBytesToRead
)
61 throw BufferSizeExceededException(OUString(),*this);
63 std::scoped_lock
aGuard( m_aMutex
);
65 sal_Int32 nAvail
= avail();
67 if (nAvail
< nBytesToRead
)
68 nBytesToRead
= nAvail
;
70 aData
.realloc(nBytesToRead
);
71 memcpy(aData
.getArray(), m_pMemoryData
+ m_nPos
, nBytesToRead
);
72 m_nPos
+= nBytesToRead
;
77 sal_Int32
MemoryInputStream::readSomeBytes( sal_Int8
* pData
, sal_Int32 nBytesToRead
)
80 throw BufferSizeExceededException(OUString(),*this);
82 std::scoped_lock
aGuard( m_aMutex
);
84 sal_Int32 nAvail
= avail();
86 if (nAvail
< nBytesToRead
)
87 nBytesToRead
= nAvail
;
89 memcpy(pData
, m_pMemoryData
+ m_nPos
, nBytesToRead
);
90 m_nPos
+= nBytesToRead
;
95 sal_Int32 SAL_CALL
MemoryInputStream::readSomeBytes( Sequence
<sal_Int8
>& aData
, sal_Int32 nMaxBytesToRead
)
97 // all data is available at once
98 return readBytes(aData
, nMaxBytesToRead
);
102 void SAL_CALL
MemoryInputStream::skipBytes( sal_Int32 nBytesToSkip
)
104 if (nBytesToSkip
< 0)
105 throw BufferSizeExceededException(OUString(),*this);
107 std::scoped_lock
aGuard( m_aMutex
);
109 sal_Int32 nAvail
= avail();
111 if (nAvail
< nBytesToSkip
)
112 nBytesToSkip
= nAvail
;
114 m_nPos
+= nBytesToSkip
;
118 sal_Int32 SAL_CALL
MemoryInputStream::available( )
120 std::scoped_lock
aGuard( m_aMutex
);
126 void SAL_CALL
MemoryInputStream::closeInput( )
128 std::scoped_lock
aGuard( m_aMutex
);
131 throw NotConnectedException(OUString(), *this);
136 void SAL_CALL
MemoryInputStream::seek( sal_Int64 location
)
138 if ( location
> m_nMemoryDataLength
|| location
< 0 || location
> SAL_MAX_INT32
)
139 throw IllegalArgumentException(u
"bad location"_ustr
, static_cast<cppu::OWeakObject
*>(this), 1);
140 std::scoped_lock
aGuard( m_aMutex
);
141 m_nPos
= static_cast<sal_Int32
>(location
);
144 sal_Int64 SAL_CALL
MemoryInputStream::getPosition()
146 std::scoped_lock
aGuard( m_aMutex
);
150 sal_Int64 SAL_CALL
MemoryInputStream::getLength( )
152 return m_nMemoryDataLength
;
156 SequenceInputStream::SequenceInputStream(
157 css::uno::Sequence
<sal_Int8
> const & rData
)
158 : MemoryInputStream(rData
.getConstArray(), rData
.getLength())
164 OSequenceOutputStream::OSequenceOutputStream(Sequence
< sal_Int8
>& _rSeq
, double _nResizeFactor
, sal_Int32 _nMinimumResize
)
166 ,m_nResizeFactor(_nResizeFactor
)
167 ,m_nMinimumResize(_nMinimumResize
)
168 ,m_nSize(0) // starting at position 0
171 OSL_ENSURE(m_nResizeFactor
> 1, "OSequenceOutputStream::OSequenceOutputStream : invalid resize factor !");
173 if (m_nResizeFactor
<= 1)
174 m_nResizeFactor
= 1.3;
178 void SAL_CALL
OSequenceOutputStream::writeBytes( const Sequence
< sal_Int8
>& _rData
)
180 std::scoped_lock
aGuard(m_aMutex
);
182 throw NotConnectedException();
184 // ensure the sequence has enough space left
185 if (m_nSize
+ _rData
.getLength() > m_rSequence
.getLength())
187 sal_Int32 nCurrentLength
= m_rSequence
.getLength();
188 sal_Int32 nNewLength
= static_cast< sal_Int32
>(
189 nCurrentLength
* m_nResizeFactor
);
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
;
195 if (nNewLength
< m_nSize
+ _rData
.getLength())
196 { // it's not enough... the data would not fit
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
;
204 // round it off to the next multiple of 4...
205 nNewLength
= (nNewLength
+ 3) / 4 * 4;
207 m_rSequence
.realloc(nNewLength
);
210 OSL_ENSURE(m_rSequence
.getLength() >= m_nSize
+ _rData
.getLength(),
211 "ooops ... the realloc algorithm seems to be wrong :( !");
213 memcpy(m_rSequence
.getArray() + m_nSize
, _rData
.getConstArray(), _rData
.getLength());
214 m_nSize
+= _rData
.getLength();
218 void SAL_CALL
OSequenceOutputStream::flush( )
220 std::scoped_lock
aGuard(m_aMutex
);
222 throw NotConnectedException();
224 // cut the sequence to the real size
225 m_rSequence
.realloc(m_nSize
);
228 void OSequenceOutputStream::finalizeOutput()
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;
236 void SAL_CALL
OSequenceOutputStream::closeOutput()
238 std::scoped_lock
aGuard(m_aMutex
);
240 throw NotConnectedException();
245 } // namespace comphelper
247 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */