1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_comphelper.hxx" 30 #include <comphelper/seqstream.hxx> 31 32 #include <memory.h> // for memcpy 33 34 namespace comphelper 35 { 36 using namespace ::com::sun::star::lang; 37 using namespace ::com::sun::star::io; 38 using namespace ::com::sun::star::uno; 39 using namespace ::osl; 40 41 //--------------------------------------------------------------------------------------------- 42 // class SequenceInputStream 43 //--------------------------------------------------------------------------------------------- 44 45 //------------------------------------------------------------------ 46 SequenceInputStream::SequenceInputStream(const ByteSequence& rData) 47 : m_aData(rData) 48 , m_nPos(0) 49 { 50 } 51 52 // checks if closed, returns available size, not mutex-protected 53 //------------------------------------------------------------------ 54 inline sal_Int32 SequenceInputStream::avail() 55 { 56 if (m_nPos == -1) 57 throw NotConnectedException(::rtl::OUString(), *this); 58 59 return m_aData.getLength() - m_nPos; 60 } 61 62 // com::sun::star::io::XInputStream 63 //------------------------------------------------------------------ 64 sal_Int32 SAL_CALL SequenceInputStream::readBytes( Sequence<sal_Int8>& aData, sal_Int32 nBytesToRead ) 65 throw(NotConnectedException, BufferSizeExceededException, 66 IOException, RuntimeException) 67 { 68 ::osl::MutexGuard aGuard( m_aMutex ); 69 70 sal_Int32 nAvail = avail(); 71 72 if (nBytesToRead < 0) 73 throw BufferSizeExceededException(::rtl::OUString(),*this); 74 75 if (nAvail < nBytesToRead) 76 nBytesToRead = nAvail; 77 78 aData.realloc(nBytesToRead); 79 memcpy(aData.getArray(), m_aData.getConstArray() + m_nPos, nBytesToRead); 80 m_nPos += nBytesToRead; 81 82 return nBytesToRead; 83 } 84 85 //------------------------------------------------------------------ 86 sal_Int32 SAL_CALL SequenceInputStream::readSomeBytes( Sequence<sal_Int8>& aData, sal_Int32 nMaxBytesToRead ) 87 throw(NotConnectedException, BufferSizeExceededException, 88 IOException, RuntimeException) 89 { 90 // all data is available at once 91 return readBytes(aData, nMaxBytesToRead); 92 } 93 94 //------------------------------------------------------------------ 95 void SAL_CALL SequenceInputStream::skipBytes( sal_Int32 nBytesToSkip ) 96 throw(NotConnectedException, BufferSizeExceededException, 97 IOException, RuntimeException) 98 { 99 ::osl::MutexGuard aGuard( m_aMutex ); 100 101 sal_Int32 nAvail = avail(); 102 103 if (nBytesToSkip < 0) 104 throw BufferSizeExceededException(::rtl::OUString(),*this); 105 106 if (nAvail < nBytesToSkip) 107 nBytesToSkip = nAvail; 108 109 m_nPos += nBytesToSkip; 110 } 111 112 //------------------------------------------------------------------ 113 sal_Int32 SAL_CALL SequenceInputStream::available( ) 114 throw(NotConnectedException, IOException, RuntimeException) 115 { 116 ::osl::MutexGuard aGuard( m_aMutex ); 117 118 return avail(); 119 } 120 121 //------------------------------------------------------------------ 122 void SAL_CALL SequenceInputStream::closeInput( ) 123 throw(NotConnectedException, IOException, RuntimeException) 124 { 125 if (m_nPos == -1) 126 throw NotConnectedException(::rtl::OUString(), *this); 127 128 m_nPos = -1; 129 } 130 131 void SAL_CALL SequenceInputStream::seek( sal_Int64 location ) throw (IllegalArgumentException, IOException, RuntimeException) 132 { 133 if ( location > m_aData.getLength() || location < 0 || location > SAL_MAX_INT32 ) 134 throw IllegalArgumentException(); 135 m_nPos = (sal_Int32) location; 136 } 137 138 sal_Int64 SAL_CALL SequenceInputStream::getPosition() throw (IOException, RuntimeException) 139 { 140 return m_nPos; 141 } 142 143 sal_Int64 SAL_CALL SequenceInputStream::getLength( ) throw (IOException, RuntimeException) 144 { 145 return m_aData.getLength(); 146 } 147 148 //-------------------------------------------------------------------------- 149 OSequenceOutputStream::OSequenceOutputStream(Sequence< sal_Int8 >& _rSeq, double _nResizeFactor, sal_Int32 _nMinimumResize, sal_Int32 _nMaximumResize) 150 :m_rSequence(_rSeq) 151 ,m_nResizeFactor(_nResizeFactor) 152 ,m_nMinimumResize(_nMinimumResize) 153 ,m_nMaximumResize(_nMaximumResize) 154 ,m_nSize(0) // starting at position 0 155 ,m_bConnected(sal_True) 156 { 157 OSL_ENSURE(m_nResizeFactor > 1, "OSequenceOutputStream::OSequenceOutputStream : invalid resize factor !"); 158 OSL_ENSURE((m_nMaximumResize < 0) || (m_nMaximumResize > m_nMinimumResize), 159 "OSequenceOutputStream::OSequenceOutputStream : these limits don't make any sense !"); 160 161 if (m_nResizeFactor <= 1) 162 m_nResizeFactor = 1.3; 163 if ((m_nMaximumResize >= 0) && (m_nMaximumResize <= m_nMinimumResize)) 164 m_nMaximumResize = m_nMinimumResize * 2; 165 // this heuristic is as good as any other ... supply better parameters if you don't like it :) 166 } 167 168 //-------------------------------------------------------------------------- 169 void SAL_CALL OSequenceOutputStream::writeBytes( const Sequence< sal_Int8 >& _rData ) throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) 170 { 171 MutexGuard aGuard(m_aMutex); 172 if (!m_bConnected) 173 throw NotConnectedException(); 174 175 // ensure the sequence has enoungh space left 176 if (m_nSize + _rData.getLength() > m_rSequence.getLength()) 177 { 178 sal_Int32 nCurrentLength = m_rSequence.getLength(); 179 sal_Int32 nNewLength = static_cast< sal_Int32 >( 180 nCurrentLength * m_nResizeFactor); 181 182 if (m_nMinimumResize > nNewLength - nCurrentLength) 183 // we have a minimum so it's not too inefficient for small sequences and small write requests 184 nNewLength = nCurrentLength + m_nMinimumResize; 185 186 if ((m_nMaximumResize > 0) && (nNewLength - nCurrentLength > m_nMaximumResize)) 187 // such a large step is not allowed 188 nNewLength = nCurrentLength + m_nMaximumResize; 189 190 if (nNewLength < m_nSize + _rData.getLength()) 191 { // it's not enough .... the data would not fit 192 193 // let's take the double amount of the length of the data to be written, as the next write 194 // request could be as large as this one 195 sal_Int32 nNewGrowth = _rData.getLength() * 2; 196 if ((m_nMaximumResize > 0) && (nNewGrowth > m_nMaximumResize)) 197 { // we came to the limit, again ... 198 nNewGrowth = m_nMaximumResize; 199 if (nNewGrowth + nCurrentLength < m_nSize + _rData.getLength()) 200 // but it would not fit if we respect the limit 201 nNewGrowth = m_nSize + _rData.getLength() - nCurrentLength; 202 } 203 nNewLength = nCurrentLength + nNewGrowth; 204 } 205 206 // round it off to the next multiple of 4 ... 207 nNewLength = (nNewLength + 3) / 4 * 4; 208 209 m_rSequence.realloc(nNewLength); 210 } 211 212 OSL_ENSURE(m_rSequence.getLength() >= m_nSize + _rData.getLength(), 213 "ooops ... the realloc algorithm seems to be wrong :( !"); 214 215 memcpy(m_rSequence.getArray() + m_nSize, _rData.getConstArray(), _rData.getLength()); 216 m_nSize += _rData.getLength(); 217 } 218 219 //-------------------------------------------------------------------------- 220 void SAL_CALL OSequenceOutputStream::flush( ) throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) 221 { 222 MutexGuard aGuard(m_aMutex); 223 if (!m_bConnected) 224 throw NotConnectedException(); 225 226 // cut the sequence to the real size 227 m_rSequence.realloc(m_nSize); 228 } 229 230 //-------------------------------------------------------------------------- 231 void SAL_CALL OSequenceOutputStream::closeOutput( ) throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) 232 { 233 MutexGuard aGuard(m_aMutex); 234 if (!m_bConnected) 235 throw NotConnectedException(); 236 237 // cut the sequence to the real size 238 m_rSequence.realloc(m_nSize); 239 // and don't allow any further accesses 240 m_bConnected = sal_False; 241 } 242 243 } // namespace comphelper 244