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 #include "oox/helper/binaryinputstream.hxx" 29 30 #include <com/sun/star/io/XInputStream.hpp> 31 #include <com/sun/star/io/XSeekable.hpp> 32 #include <string.h> 33 #include <vector> 34 #include <rtl/strbuf.hxx> 35 #include <rtl/ustrbuf.hxx> 36 #include "oox/helper/binaryoutputstream.hxx" 37 38 namespace oox { 39 40 // ============================================================================ 41 42 using namespace ::com::sun::star::io; 43 using namespace ::com::sun::star::uno; 44 45 using ::rtl::OString; 46 using ::rtl::OStringBuffer; 47 using ::rtl::OStringToOUString; 48 using ::rtl::OUString; 49 using ::rtl::OUStringBuffer; 50 51 namespace { 52 53 const sal_Int32 INPUTSTREAM_BUFFERSIZE = 0x8000; 54 55 } // namespace 56 57 // ============================================================================ 58 59 OString BinaryInputStream::readNulCharArray() 60 { 61 OStringBuffer aBuffer; 62 for( sal_uInt8 nChar = readuInt8(); !mbEof && (nChar > 0); readValue( nChar ) ) 63 aBuffer.append( static_cast< sal_Char >( nChar ) ); 64 return aBuffer.makeStringAndClear(); 65 } 66 67 OUString BinaryInputStream::readNulCharArrayUC( rtl_TextEncoding eTextEnc ) 68 { 69 return OStringToOUString( readNulCharArray(), eTextEnc ); 70 } 71 72 OUString BinaryInputStream::readNulUnicodeArray() 73 { 74 OUStringBuffer aBuffer; 75 for( sal_uInt16 nChar = readuInt16(); !mbEof && (nChar > 0); readValue( nChar ) ) 76 aBuffer.append( static_cast< sal_Unicode >( nChar ) ); 77 return aBuffer.makeStringAndClear(); 78 } 79 80 OString BinaryInputStream::readCharArray( sal_Int32 nChars, bool bAllowNulChars ) 81 { 82 if( nChars <= 0 ) 83 return OString(); 84 85 ::std::vector< sal_uInt8 > aBuffer; 86 sal_Int32 nCharsRead = readArray( aBuffer, nChars ); 87 if( nCharsRead <= 0 ) 88 return OString(); 89 90 aBuffer.resize( static_cast< size_t >( nCharsRead ) ); 91 if( !bAllowNulChars ) 92 ::std::replace( aBuffer.begin(), aBuffer.end(), '\0', '?' ); 93 94 return OString( reinterpret_cast< sal_Char* >( &aBuffer.front() ), nCharsRead ); 95 } 96 97 OUString BinaryInputStream::readCharArrayUC( sal_Int32 nChars, rtl_TextEncoding eTextEnc, bool bAllowNulChars ) 98 { 99 return OStringToOUString( readCharArray( nChars, bAllowNulChars ), eTextEnc ); 100 } 101 102 OUString BinaryInputStream::readUnicodeArray( sal_Int32 nChars, bool bAllowNulChars ) 103 { 104 if( nChars <= 0 ) 105 return OUString(); 106 107 ::std::vector< sal_uInt16 > aBuffer; 108 sal_Int32 nCharsRead = readArray( aBuffer, nChars ); 109 if( nCharsRead <= 0 ) 110 return OUString(); 111 112 aBuffer.resize( static_cast< size_t >( nCharsRead ) ); 113 if( !bAllowNulChars ) 114 ::std::replace( aBuffer.begin(), aBuffer.begin() + nCharsRead, '\0', '?' ); 115 116 OUStringBuffer aStringBuffer; 117 aStringBuffer.ensureCapacity( nCharsRead ); 118 for( ::std::vector< sal_uInt16 >::iterator aIt = aBuffer.begin(), aEnd = aBuffer.end(); aIt != aEnd; ++aIt ) 119 aStringBuffer.append( static_cast< sal_Unicode >( *aIt ) ); 120 return aStringBuffer.makeStringAndClear(); 121 } 122 123 OUString BinaryInputStream::readCompressedUnicodeArray( sal_Int32 nChars, bool bCompressed, bool bAllowNulChars ) 124 { 125 return bCompressed ? 126 // ISO-8859-1 maps all byte values 0xHH to the same Unicode code point U+00HH 127 readCharArrayUC( nChars, RTL_TEXTENCODING_ISO_8859_1, bAllowNulChars ) : 128 readUnicodeArray( nChars, bAllowNulChars ); 129 } 130 131 void BinaryInputStream::copyToStream( BinaryOutputStream& rOutStrm, sal_Int64 nBytes, sal_Int32 nAtomSize ) 132 { 133 if( nBytes > 0 ) 134 { 135 // make buffer size a multiple of the passed atom size 136 sal_Int32 nBufferSize = getLimitedValue< sal_Int32, sal_Int64 >( nBytes, 0, (INPUTSTREAM_BUFFERSIZE / nAtomSize) * nAtomSize ); 137 StreamDataSequence aBuffer( nBufferSize ); 138 while( nBytes > 0 ) 139 { 140 sal_Int32 nReadSize = getLimitedValue< sal_Int32, sal_Int64 >( nBytes, 0, nBufferSize ); 141 sal_Int32 nBytesRead = readData( aBuffer, nReadSize, nAtomSize ); 142 rOutStrm.writeData( aBuffer ); 143 if( nReadSize == nBytesRead ) 144 nBytes -= nReadSize; 145 else 146 nBytes = 0; 147 } 148 } 149 } 150 151 // ============================================================================ 152 153 BinaryXInputStream::BinaryXInputStream( const Reference< XInputStream >& rxInStrm, bool bAutoClose ) : 154 BinaryStreamBase( Reference< XSeekable >( rxInStrm, UNO_QUERY ).is() ), 155 BinaryXSeekableStream( Reference< XSeekable >( rxInStrm, UNO_QUERY ) ), 156 maBuffer( INPUTSTREAM_BUFFERSIZE ), 157 mxInStrm( rxInStrm ), 158 mbAutoClose( bAutoClose && rxInStrm.is() ) 159 { 160 mbEof = !mxInStrm.is(); 161 } 162 163 BinaryXInputStream::~BinaryXInputStream() 164 { 165 close(); 166 } 167 168 void BinaryXInputStream::close() 169 { 170 OSL_ENSURE( !mbAutoClose || mxInStrm.is(), "BinaryXInputStream::close - invalid call" ); 171 if( mbAutoClose && mxInStrm.is() ) try 172 { 173 mxInStrm->closeInput(); 174 } 175 catch( Exception& ) 176 { 177 OSL_ENSURE( false, "BinaryXInputStream::close - closing input stream failed" ); 178 } 179 mxInStrm.clear(); 180 mbAutoClose = false; 181 BinaryXSeekableStream::close(); 182 } 183 184 sal_Int32 BinaryXInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t /*nAtomSize*/ ) 185 { 186 sal_Int32 nRet = 0; 187 if( !mbEof && (nBytes > 0) ) try 188 { 189 nRet = mxInStrm->readBytes( orData, nBytes ); 190 mbEof = nRet != nBytes; 191 } 192 catch( Exception& ) 193 { 194 mbEof = true; 195 } 196 return nRet; 197 } 198 199 sal_Int32 BinaryXInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize ) 200 { 201 sal_Int32 nRet = 0; 202 if( !mbEof && (nBytes > 0) ) 203 { 204 sal_Int32 nBufferSize = getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, INPUTSTREAM_BUFFERSIZE ); 205 sal_uInt8* opnMem = reinterpret_cast< sal_uInt8* >( opMem ); 206 while( !mbEof && (nBytes > 0) ) 207 { 208 sal_Int32 nReadSize = getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, nBufferSize ); 209 sal_Int32 nBytesRead = readData( maBuffer, nReadSize, nAtomSize ); 210 if( nBytesRead > 0 ) 211 memcpy( opnMem, maBuffer.getConstArray(), static_cast< size_t >( nBytesRead ) ); 212 opnMem += nBytesRead; 213 nBytes -= nBytesRead; 214 nRet += nBytesRead; 215 } 216 } 217 return nRet; 218 } 219 220 void BinaryXInputStream::skip( sal_Int32 nBytes, size_t /*nAtomSize*/ ) 221 { 222 if( !mbEof ) try 223 { 224 mxInStrm->skipBytes( nBytes ); 225 } 226 catch( Exception& ) 227 { 228 mbEof = true; 229 } 230 } 231 232 // ============================================================================ 233 234 SequenceInputStream::SequenceInputStream( const StreamDataSequence& rData ) : 235 BinaryStreamBase( true ), 236 SequenceSeekableStream( rData ) 237 { 238 } 239 240 sal_Int32 SequenceInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t /*nAtomSize*/ ) 241 { 242 sal_Int32 nReadBytes = 0; 243 if( !mbEof ) 244 { 245 nReadBytes = getMaxBytes( nBytes ); 246 orData.realloc( nReadBytes ); 247 if( nReadBytes > 0 ) 248 memcpy( orData.getArray(), mpData->getConstArray() + mnPos, static_cast< size_t >( nReadBytes ) ); 249 mnPos += nReadBytes; 250 mbEof = nReadBytes < nBytes; 251 } 252 return nReadBytes; 253 } 254 255 sal_Int32 SequenceInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t /*nAtomSize*/ ) 256 { 257 sal_Int32 nReadBytes = 0; 258 if( !mbEof ) 259 { 260 nReadBytes = getMaxBytes( nBytes ); 261 if( nReadBytes > 0 ) 262 memcpy( opMem, mpData->getConstArray() + mnPos, static_cast< size_t >( nReadBytes ) ); 263 mnPos += nReadBytes; 264 mbEof = nReadBytes < nBytes; 265 } 266 return nReadBytes; 267 } 268 269 void SequenceInputStream::skip( sal_Int32 nBytes, size_t /*nAtomSize*/ ) 270 { 271 if( !mbEof ) 272 { 273 sal_Int32 nSkipBytes = getMaxBytes( nBytes ); 274 mnPos += nSkipBytes; 275 mbEof = nSkipBytes < nBytes; 276 } 277 } 278 279 // ============================================================================ 280 281 RelativeInputStream::RelativeInputStream( BinaryInputStream& rInStrm, sal_Int64 nSize ) : 282 BinaryStreamBase( rInStrm.isSeekable() ), 283 mpInStrm( &rInStrm ), 284 mnStartPos( rInStrm.tell() ), 285 mnRelPos( 0 ) 286 { 287 sal_Int64 nRemaining = rInStrm.getRemaining(); 288 mnSize = (nRemaining >= 0) ? ::std::min( nSize, nRemaining ) : nSize; 289 mbEof = mbEof || rInStrm.isEof() || (mnSize < 0); 290 } 291 292 sal_Int64 RelativeInputStream::size() const 293 { 294 return mpInStrm ? mnSize : -1; 295 } 296 297 sal_Int64 RelativeInputStream::tell() const 298 { 299 return mpInStrm ? mnRelPos : -1; 300 } 301 302 void RelativeInputStream::seek( sal_Int64 nPos ) 303 { 304 if( mpInStrm && isSeekable() && (mnStartPos >= 0) ) 305 { 306 mnRelPos = getLimitedValue< sal_Int64, sal_Int64 >( nPos, 0, mnSize ); 307 mpInStrm->seek( mnStartPos + mnRelPos ); 308 mbEof = (mnRelPos != nPos) || mpInStrm->isEof(); 309 } 310 } 311 312 void RelativeInputStream::close() 313 { 314 mpInStrm = 0; 315 mbEof = true; 316 } 317 318 sal_Int32 RelativeInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize ) 319 { 320 sal_Int32 nReadBytes = 0; 321 if( !mbEof ) 322 { 323 sal_Int32 nMaxBytes = getMaxBytes( nBytes ); 324 nReadBytes = mpInStrm->readData( orData, nMaxBytes, nAtomSize ); 325 mnRelPos += nReadBytes; 326 mbEof = (nMaxBytes < nBytes) || mpInStrm->isEof(); 327 } 328 return nReadBytes; 329 } 330 331 sal_Int32 RelativeInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize ) 332 { 333 sal_Int32 nReadBytes = 0; 334 if( !mbEof ) 335 { 336 sal_Int32 nMaxBytes = getMaxBytes( nBytes ); 337 nReadBytes = mpInStrm->readMemory( opMem, nMaxBytes, nAtomSize ); 338 mnRelPos += nReadBytes; 339 mbEof = (nMaxBytes < nBytes) || mpInStrm->isEof(); 340 } 341 return nReadBytes; 342 } 343 344 void RelativeInputStream::skip( sal_Int32 nBytes, size_t nAtomSize ) 345 { 346 if( !mbEof ) 347 { 348 sal_Int32 nSkipBytes = getMaxBytes( nBytes ); 349 mpInStrm->skip( nSkipBytes, nAtomSize ); 350 mnRelPos += nSkipBytes; 351 mbEof = nSkipBytes < nBytes; 352 } 353 } 354 355 // ============================================================================ 356 357 } // namespace oox 358