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>
25 #include <comphelper/seqstream.hxx>
26 
27 #include <osl/diagnose.h>
28 
29 namespace comphelper
30 {
31 using namespace ::com::sun::star::lang;
32 using namespace ::com::sun::star::io;
33 using namespace ::com::sun::star::uno;
34 using namespace ::osl;
35 
36 
37 
38 
40  css::uno::Sequence<sal_Int8> const & rData)
41 : m_aData(rData)
42 , m_nPos(0)
43 {
44 }
45 
46 // checks if closed, returns available size, not mutex-protected
47 
48 inline sal_Int32 SequenceInputStream::avail()
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 
58 sal_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 
77 
78 sal_Int32 SAL_CALL SequenceInputStream::readSomeBytes( Sequence<sal_Int8>& aData, sal_Int32 nMaxBytesToRead )
79 {
80  // all data is available at once
81  return readBytes(aData, nMaxBytesToRead);
82 }
83 
84 
85 void SAL_CALL SequenceInputStream::skipBytes( sal_Int32 nBytesToSkip )
86 {
87  if (nBytesToSkip < 0)
88  throw BufferSizeExceededException(OUString(),*this);
89 
90  std::scoped_lock aGuard( m_aMutex );
91 
92  sal_Int32 nAvail = avail();
93 
94  if (nAvail < nBytesToSkip)
95  nBytesToSkip = nAvail;
96 
97  m_nPos += nBytesToSkip;
98 }
99 
100 
101 sal_Int32 SAL_CALL SequenceInputStream::available( )
102 {
103  std::scoped_lock aGuard( m_aMutex );
104 
105  return avail();
106 }
107 
108 
110 {
111  std::scoped_lock aGuard( m_aMutex );
112 
113  if (m_nPos == -1)
114  throw NotConnectedException(OUString(), *this);
115 
116  m_nPos = -1;
117 }
118 
119 void SAL_CALL SequenceInputStream::seek( sal_Int64 location )
120 {
121  if ( location > m_aData.getLength() || location < 0 || location > SAL_MAX_INT32 )
122  throw IllegalArgumentException("bad location", static_cast<cppu::OWeakObject*>(this), 1);
123  std::scoped_lock aGuard( m_aMutex );
124  m_nPos = static_cast<sal_Int32>(location);
125 }
126 
128 {
129  std::scoped_lock aGuard( m_aMutex );
130  return m_nPos;
131 }
132 
133 sal_Int64 SAL_CALL SequenceInputStream::getLength( )
134 {
135  std::scoped_lock aGuard( m_aMutex );
136  return m_aData.getLength();
137 }
138 
139 
140 OSequenceOutputStream::OSequenceOutputStream(Sequence< sal_Int8 >& _rSeq, double _nResizeFactor, sal_Int32 _nMinimumResize)
141  :m_rSequence(_rSeq)
142  ,m_nResizeFactor(_nResizeFactor)
143  ,m_nMinimumResize(_nMinimumResize)
144  ,m_nSize(0) // starting at position 0
145  ,m_bConnected(true)
146 {
147  OSL_ENSURE(m_nResizeFactor > 1, "OSequenceOutputStream::OSequenceOutputStream : invalid resize factor !");
148 
149  if (m_nResizeFactor <= 1)
150  m_nResizeFactor = 1.3;
151 }
152 
153 
154 void SAL_CALL OSequenceOutputStream::writeBytes( const Sequence< sal_Int8 >& _rData )
155 {
156  std::scoped_lock aGuard(m_aMutex);
157  if (!m_bConnected)
158  throw NotConnectedException();
159 
160  // ensure the sequence has enough space left
161  if (m_nSize + _rData.getLength() > m_rSequence.getLength())
162  {
163  sal_Int32 nCurrentLength = m_rSequence.getLength();
164  sal_Int32 nNewLength = static_cast< sal_Int32 >(
165  nCurrentLength * m_nResizeFactor);
166 
167  if (m_nMinimumResize > nNewLength - nCurrentLength)
168  // we have a minimum so it's not too inefficient for small sequences and small write requests
169  nNewLength = nCurrentLength + m_nMinimumResize;
170 
171  if (nNewLength < m_nSize + _rData.getLength())
172  { // it's not enough... the data would not fit
173 
174  // let's take the double amount of the length of the data to be written, as the next write
175  // request could be as large as this one
176  sal_Int32 nNewGrowth = _rData.getLength() * 2;
177  nNewLength = nCurrentLength + nNewGrowth;
178  }
179 
180  // round it off to the next multiple of 4...
181  nNewLength = (nNewLength + 3) / 4 * 4;
182 
183  m_rSequence.realloc(nNewLength);
184  }
185 
186  OSL_ENSURE(m_rSequence.getLength() >= m_nSize + _rData.getLength(),
187  "ooops ... the realloc algorithm seems to be wrong :( !");
188 
189  memcpy(m_rSequence.getArray() + m_nSize, _rData.getConstArray(), _rData.getLength());
190  m_nSize += _rData.getLength();
191 }
192 
193 
194 void SAL_CALL OSequenceOutputStream::flush( )
195 {
196  std::scoped_lock aGuard(m_aMutex);
197  if (!m_bConnected)
198  throw NotConnectedException();
199 
200  // cut the sequence to the real size
201  m_rSequence.realloc(m_nSize);
202 }
203 
204 void OSequenceOutputStream::finalizeOutput()
205 {
206  // cut the sequence to the real size
207  m_rSequence.realloc(m_nSize);
208  // and don't allow any further accesses
209  m_bConnected = false;
210 }
211 
212 void SAL_CALL OSequenceOutputStream::closeOutput()
213 {
214  std::scoped_lock aGuard(m_aMutex);
215  if (!m_bConnected)
216  throw NotConnectedException();
217 
218  finalizeOutput();
219 }
220 
221 } // namespace comphelper
222 
223 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
size_t m_nPos
::osl::Mutex m_aMutex
virtual void SAL_CALL seek(sal_Int64 location) override
Definition: seqstream.cxx:119
virtual sal_Int64 SAL_CALL getLength() override
Definition: seqstream.cxx:133
virtual sal_Int32 SAL_CALL available() override
Definition: seqstream.cxx:101
MapData m_aData
virtual sal_Int64 SAL_CALL getPosition() override
Definition: seqstream.cxx:127
SequenceInputStream(css::uno::Sequence< sal_Int8 > const &rData)
Definition: seqstream.cxx:39
#define SAL_MAX_INT32
virtual void SAL_CALL closeInput() override
Definition: seqstream.cxx:109
virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) override
Definition: seqstream.cxx:85
css::uno::Sequence< sal_Int8 > const m_aData
Definition: seqstream.hxx:43
virtual sal_Int32 SAL_CALL readBytes(css::uno::Sequence< sal_Int8 > &aData, sal_Int32 nBytesToRead) override
virtual sal_Int32 SAL_CALL readSomeBytes(css::uno::Sequence< sal_Int8 > &aData, sal_Int32 nMaxBytesToRead) override
sal_uInt32 m_nSize