1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_io.hxx" 26 #include <rtl/alloc.h> 27 28 #include <limits> 29 #include <string.h> 30 31 #include <com/sun/star/uno/Sequence.hxx> 32 33 #include <com/sun/star/uno/Exception.hpp> 34 35 using namespace ::com::sun::star::uno; 36 37 #include "streamhelper.hxx" 38 39 namespace io_stm { 40 41 void MemFIFO::write( const Sequence< sal_Int8 > &seq ) 42 throw ( IFIFO_OutOfMemoryException, 43 IFIFO_OutOfBoundsException ) 44 { 45 try 46 { 47 writeAt(getSize(), seq ); 48 } 49 catch( IRingBuffer_OutOfMemoryException & ) 50 { 51 throw IFIFO_OutOfMemoryException(); 52 } 53 catch( IRingBuffer_OutOfBoundsException & ) 54 { 55 throw IFIFO_OutOfBoundsException(); 56 } 57 } 58 59 void MemFIFO::read( Sequence<sal_Int8> &seq , sal_Int32 nBufferLen ) throw (IFIFO_OutOfBoundsException) 60 { 61 try 62 { 63 readAt(0, seq , nBufferLen); 64 forgetFromStart( nBufferLen ); 65 } 66 catch ( IRingBuffer_OutOfBoundsException & ) 67 { 68 throw IFIFO_OutOfBoundsException(); 69 } 70 } 71 72 void MemFIFO::skip( sal_Int32 nBytesToSkip ) throw ( IFIFO_OutOfBoundsException ) 73 { 74 try 75 { 76 forgetFromStart( nBytesToSkip ); 77 } 78 catch( IRingBuffer_OutOfBoundsException & ) 79 { 80 throw IFIFO_OutOfBoundsException(); 81 } 82 } 83 84 85 86 MemRingBuffer::MemRingBuffer() 87 { 88 m_nBufferLen = 0; 89 m_p = 0; 90 m_nStart = 0; 91 m_nOccupiedBuffer = 0; 92 } 93 94 MemRingBuffer::~MemRingBuffer() 95 { 96 if( m_p ) { 97 rtl_freeMemory( m_p ); 98 } 99 } 100 101 void MemRingBuffer::resizeBuffer( sal_Int32 nMinSize ) throw( IRingBuffer_OutOfMemoryException) 102 { 103 sal_Int32 nNewLen = 1; 104 105 while( nMinSize > nNewLen ) { 106 nNewLen = nNewLen << 1; 107 } 108 109 // buffer never shrinks ! 110 if( nNewLen < m_nBufferLen ) { 111 nNewLen = m_nBufferLen; 112 } 113 114 if( nNewLen != m_nBufferLen ) { 115 m_p = ( sal_Int8 * ) rtl_reallocateMemory( m_p , nNewLen ); 116 if( !m_p ) { 117 throw IRingBuffer_OutOfMemoryException(); 118 } 119 120 if( m_nStart + m_nOccupiedBuffer > m_nBufferLen ) { 121 memmove( &( m_p[m_nStart+(nNewLen-m_nBufferLen)]) , &(m_p[m_nStart]) , m_nBufferLen - m_nStart ); 122 m_nStart += nNewLen - m_nBufferLen; 123 } 124 m_nBufferLen = nNewLen; 125 } 126 } 127 128 129 void MemRingBuffer::readAt( sal_Int32 nPos, Sequence<sal_Int8> &seq , sal_Int32 nBytesToRead ) const 130 throw(IRingBuffer_OutOfBoundsException) 131 { 132 if( nPos + nBytesToRead > m_nOccupiedBuffer ) { 133 throw IRingBuffer_OutOfBoundsException(); 134 } 135 136 sal_Int32 nStartReadingPos = nPos + m_nStart; 137 if( nStartReadingPos >= m_nBufferLen ) { 138 nStartReadingPos -= m_nBufferLen; 139 } 140 141 seq.realloc( nBytesToRead ); 142 143 if( nStartReadingPos + nBytesToRead > m_nBufferLen ) { 144 sal_Int32 nDeltaLen = m_nBufferLen - nStartReadingPos; 145 memcpy( seq.getArray() , &(m_p[nStartReadingPos]) , nDeltaLen ); 146 memcpy( &(seq.getArray()[nDeltaLen]), m_p , nBytesToRead - nDeltaLen ); 147 } 148 else { 149 memcpy( seq.getArray() , &(m_p[nStartReadingPos]) , nBytesToRead ); 150 } 151 } 152 153 154 void MemRingBuffer::writeAt( sal_Int32 nPos, const Sequence<sal_Int8> &seq ) 155 throw (IRingBuffer_OutOfBoundsException, 156 IRingBuffer_OutOfMemoryException ) 157 { 158 checkInvariants(); 159 sal_Int32 nLen = seq.getLength(); 160 161 if( nPos < 0 || nPos > std::numeric_limits< sal_Int32 >::max() - nLen ) 162 { 163 throw IRingBuffer_OutOfBoundsException(); 164 } 165 166 if( nPos + nLen - m_nOccupiedBuffer > 0 ) { 167 resizeBuffer( nPos + seq.getLength() ); 168 } 169 170 sal_Int32 nStartWritingIndex = m_nStart + nPos; 171 if( nStartWritingIndex >= m_nBufferLen ) { 172 nStartWritingIndex -= m_nBufferLen; 173 } 174 175 if( nLen + nStartWritingIndex > m_nBufferLen ) { 176 // two area copy 177 memcpy( &(m_p[nStartWritingIndex]) , seq.getConstArray(), m_nBufferLen-nStartWritingIndex ); 178 memcpy( m_p , &( seq.getConstArray()[m_nBufferLen-nStartWritingIndex] ), 179 nLen - (m_nBufferLen-nStartWritingIndex) ); 180 181 } 182 else { 183 // one area copy 184 memcpy( &( m_p[nStartWritingIndex]), seq.getConstArray() , nLen ); 185 } 186 m_nOccupiedBuffer = Max( nPos + seq.getLength() , m_nOccupiedBuffer ); 187 checkInvariants(); 188 } 189 190 191 sal_Int32 MemRingBuffer::getSize() const throw() 192 { 193 return m_nOccupiedBuffer; 194 } 195 196 void MemRingBuffer::forgetFromStart( sal_Int32 nBytesToForget ) throw (IRingBuffer_OutOfBoundsException) 197 { 198 checkInvariants(); 199 if( nBytesToForget > m_nOccupiedBuffer ) { 200 throw IRingBuffer_OutOfBoundsException(); 201 } 202 m_nStart += nBytesToForget; 203 if( m_nStart >= m_nBufferLen ) { 204 m_nStart = m_nStart - m_nBufferLen; 205 } 206 m_nOccupiedBuffer -= nBytesToForget; 207 checkInvariants(); 208 } 209 210 211 void MemRingBuffer::forgetFromEnd( sal_Int32 nBytesToForget ) throw (IRingBuffer_OutOfBoundsException) 212 { 213 checkInvariants(); 214 if( nBytesToForget > m_nOccupiedBuffer ) { 215 throw IRingBuffer_OutOfBoundsException(); 216 } 217 m_nOccupiedBuffer -= nBytesToForget; 218 checkInvariants(); 219 } 220 221 222 void MemRingBuffer::shrink() throw () 223 { 224 checkInvariants(); 225 226 // Up to now, only shrinking of while buffer works. 227 // No other shrinking supported up to now. 228 if( ! m_nOccupiedBuffer ) { 229 if( m_p ) { 230 free( m_p ); 231 } 232 m_p = 0; 233 m_nBufferLen = 0; 234 m_nStart = 0; 235 } 236 237 checkInvariants(); 238 } 239 240 } 241