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_io.hxx" 30 #include <rtl/alloc.h> 31 32 #include <limits> 33 #include <string.h> 34 35 #include <com/sun/star/uno/Sequence.hxx> 36 37 #include <com/sun/star/uno/Exception.hpp> 38 39 using namespace ::com::sun::star::uno; 40 41 #include "streamhelper.hxx" 42 43 namespace io_stm { 44 45 void MemFIFO::write( const Sequence< sal_Int8 > &seq ) 46 throw ( IFIFO_OutOfMemoryException, 47 IFIFO_OutOfBoundsException ) 48 { 49 try 50 { 51 writeAt(getSize(), seq ); 52 } 53 catch( IRingBuffer_OutOfMemoryException & ) 54 { 55 throw IFIFO_OutOfMemoryException(); 56 } 57 catch( IRingBuffer_OutOfBoundsException & ) 58 { 59 throw IFIFO_OutOfBoundsException(); 60 } 61 } 62 63 void MemFIFO::read( Sequence<sal_Int8> &seq , sal_Int32 nBufferLen ) throw (IFIFO_OutOfBoundsException) 64 { 65 try 66 { 67 readAt(0, seq , nBufferLen); 68 forgetFromStart( nBufferLen ); 69 } 70 catch ( IRingBuffer_OutOfBoundsException & ) 71 { 72 throw IFIFO_OutOfBoundsException(); 73 } 74 } 75 76 void MemFIFO::skip( sal_Int32 nBytesToSkip ) throw ( IFIFO_OutOfBoundsException ) 77 { 78 try 79 { 80 forgetFromStart( nBytesToSkip ); 81 } 82 catch( IRingBuffer_OutOfBoundsException & ) 83 { 84 throw IFIFO_OutOfBoundsException(); 85 } 86 } 87 88 89 90 MemRingBuffer::MemRingBuffer() 91 { 92 m_nBufferLen = 0; 93 m_p = 0; 94 m_nStart = 0; 95 m_nOccupiedBuffer = 0; 96 } 97 98 MemRingBuffer::~MemRingBuffer() 99 { 100 if( m_p ) { 101 rtl_freeMemory( m_p ); 102 } 103 } 104 105 void MemRingBuffer::resizeBuffer( sal_Int32 nMinSize ) throw( IRingBuffer_OutOfMemoryException) 106 { 107 sal_Int32 nNewLen = 1; 108 109 while( nMinSize > nNewLen ) { 110 nNewLen = nNewLen << 1; 111 } 112 113 // buffer never shrinks ! 114 if( nNewLen < m_nBufferLen ) { 115 nNewLen = m_nBufferLen; 116 } 117 118 if( nNewLen != m_nBufferLen ) { 119 m_p = ( sal_Int8 * ) rtl_reallocateMemory( m_p , nNewLen ); 120 if( !m_p ) { 121 throw IRingBuffer_OutOfMemoryException(); 122 } 123 124 if( m_nStart + m_nOccupiedBuffer > m_nBufferLen ) { 125 memmove( &( m_p[m_nStart+(nNewLen-m_nBufferLen)]) , &(m_p[m_nStart]) , m_nBufferLen - m_nStart ); 126 m_nStart += nNewLen - m_nBufferLen; 127 } 128 m_nBufferLen = nNewLen; 129 } 130 } 131 132 133 void MemRingBuffer::readAt( sal_Int32 nPos, Sequence<sal_Int8> &seq , sal_Int32 nBytesToRead ) const 134 throw(IRingBuffer_OutOfBoundsException) 135 { 136 if( nPos + nBytesToRead > m_nOccupiedBuffer ) { 137 throw IRingBuffer_OutOfBoundsException(); 138 } 139 140 sal_Int32 nStartReadingPos = nPos + m_nStart; 141 if( nStartReadingPos >= m_nBufferLen ) { 142 nStartReadingPos -= m_nBufferLen; 143 } 144 145 seq.realloc( nBytesToRead ); 146 147 if( nStartReadingPos + nBytesToRead > m_nBufferLen ) { 148 sal_Int32 nDeltaLen = m_nBufferLen - nStartReadingPos; 149 memcpy( seq.getArray() , &(m_p[nStartReadingPos]) , nDeltaLen ); 150 memcpy( &(seq.getArray()[nDeltaLen]), m_p , nBytesToRead - nDeltaLen ); 151 } 152 else { 153 memcpy( seq.getArray() , &(m_p[nStartReadingPos]) , nBytesToRead ); 154 } 155 } 156 157 158 void MemRingBuffer::writeAt( sal_Int32 nPos, const Sequence<sal_Int8> &seq ) 159 throw (IRingBuffer_OutOfBoundsException, 160 IRingBuffer_OutOfMemoryException ) 161 { 162 checkInvariants(); 163 sal_Int32 nLen = seq.getLength(); 164 165 if( nPos < 0 || nPos > std::numeric_limits< sal_Int32 >::max() - nLen ) 166 { 167 throw IRingBuffer_OutOfBoundsException(); 168 } 169 170 if( nPos + nLen - m_nOccupiedBuffer > 0 ) { 171 resizeBuffer( nPos + seq.getLength() ); 172 } 173 174 sal_Int32 nStartWritingIndex = m_nStart + nPos; 175 if( nStartWritingIndex >= m_nBufferLen ) { 176 nStartWritingIndex -= m_nBufferLen; 177 } 178 179 if( nLen + nStartWritingIndex > m_nBufferLen ) { 180 // two area copy 181 memcpy( &(m_p[nStartWritingIndex]) , seq.getConstArray(), m_nBufferLen-nStartWritingIndex ); 182 memcpy( m_p , &( seq.getConstArray()[m_nBufferLen-nStartWritingIndex] ), 183 nLen - (m_nBufferLen-nStartWritingIndex) ); 184 185 } 186 else { 187 // one area copy 188 memcpy( &( m_p[nStartWritingIndex]), seq.getConstArray() , nLen ); 189 } 190 m_nOccupiedBuffer = Max( nPos + seq.getLength() , m_nOccupiedBuffer ); 191 checkInvariants(); 192 } 193 194 195 sal_Int32 MemRingBuffer::getSize() const throw() 196 { 197 return m_nOccupiedBuffer; 198 } 199 200 void MemRingBuffer::forgetFromStart( sal_Int32 nBytesToForget ) throw (IRingBuffer_OutOfBoundsException) 201 { 202 checkInvariants(); 203 if( nBytesToForget > m_nOccupiedBuffer ) { 204 throw IRingBuffer_OutOfBoundsException(); 205 } 206 m_nStart += nBytesToForget; 207 if( m_nStart >= m_nBufferLen ) { 208 m_nStart = m_nStart - m_nBufferLen; 209 } 210 m_nOccupiedBuffer -= nBytesToForget; 211 checkInvariants(); 212 } 213 214 215 void MemRingBuffer::forgetFromEnd( sal_Int32 nBytesToForget ) throw (IRingBuffer_OutOfBoundsException) 216 { 217 checkInvariants(); 218 if( nBytesToForget > m_nOccupiedBuffer ) { 219 throw IRingBuffer_OutOfBoundsException(); 220 } 221 m_nOccupiedBuffer -= nBytesToForget; 222 checkInvariants(); 223 } 224 225 226 void MemRingBuffer::shrink() throw () 227 { 228 checkInvariants(); 229 230 // Up to now, only shrinking of while buffer works. 231 // No other shrinking supported up to now. 232 if( ! m_nOccupiedBuffer ) { 233 if( m_p ) { 234 free( m_p ); 235 } 236 m_p = 0; 237 m_nBufferLen = 0; 238 m_nStart = 0; 239 } 240 241 checkInvariants(); 242 } 243 244 } 245