/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ // TODO: Read->RefreshBuffer-> React to changes from nBufActualLen #include #include #include #include #include #include "boost/static_assert.hpp" #include #include #define SWAPNIBBLES(c) \ unsigned char nSwapTmp=c; \ nSwapTmp <<= 4; \ c >>= 4; \ c |= nSwapTmp; #include #include #include #include // !!! Do not inline if already the operators <<,>> are inline inline static void SwapUShort( sal_uInt16& r ) { r = OSL_SWAPWORD(r); } inline static void SwapShort( short& r ) { r = OSL_SWAPWORD(r); } inline static void SwapULong( sal_uInt32& r ) { r = OSL_SWAPDWORD(r); } inline static void SwapLongInt( sal_Int32& r ) { r = OSL_SWAPDWORD(r); } inline static void SwapUInt64( sal_uInt64& r ) { union { sal_uInt64 n; sal_uInt32 c[2]; } s; s.n = r; s.c[0] ^= s.c[1]; // swap the 32 bit words s.c[1] ^= s.c[0]; s.c[0] ^= s.c[1]; // swap the bytes in the words s.c[0] = OSL_SWAPDWORD(s.c[0]); s.c[1] = OSL_SWAPDWORD(s.c[1]); r = s.n; } inline static void SwapInt64( sal_Int64& r ) { union { sal_Int64 n; sal_Int32 c[2]; } s; s.n = r; s.c[0] ^= s.c[1]; // swap the 32 bit words s.c[1] ^= s.c[0]; s.c[0] ^= s.c[1]; // swap the bytes in the words s.c[0] = OSL_SWAPDWORD(s.c[0]); s.c[1] = OSL_SWAPDWORD(s.c[1]); r = s.n; } #ifdef UNX inline static void SwapFloat( float& r ) { union { float f; sal_uInt32 c; } s; s.f = r; s.c = OSL_SWAPDWORD( s.c ); r = s.f; } inline static void SwapDouble( double& r ) { if( sizeof(double) != 8 ) { DBG_ASSERT( false, "Can only swap 8-Byte-doubles\n" ); } else { union { double d; sal_uInt32 c[2]; } s; s.d = r; s.c[0] ^= s.c[1]; // swap 32-bit values in situ s.c[1] ^= s.c[0]; s.c[0] ^= s.c[1]; s.c[0] = OSL_SWAPDWORD(s.c[0]); // swap dword itself in situ s.c[1] = OSL_SWAPDWORD(s.c[1]); r = s.d; } } #endif //SDO #define READNUMBER_WITHOUT_SWAP(datatype,value) \ if( bIoRead && sizeof(datatype)<=nBufFree) \ { \ for (std::size_t i = 0; i < sizeof(datatype); i++) \ ((char *)&value)[i] = pBufPos[i]; \ nBufActualPos += sizeof(datatype); \ pBufPos += sizeof(datatype); \ nBufFree -= sizeof(datatype); \ } \ else \ { \ Read( (char*)&value, sizeof(datatype) ); \ } \ #define WRITENUMBER_WITHOUT_SWAP(datatype,value) \ if( bIoWrite && sizeof(datatype) <= nBufFree) \ { \ for (std::size_t i = 0; i < sizeof(datatype); i++) \ pBufPos[i] = ((char *)&value)[i]; \ nBufFree -= sizeof(datatype); \ nBufActualPos += sizeof(datatype); \ if( nBufActualPos > nBufActualLen ) \ nBufActualLen = nBufActualPos; \ pBufPos += sizeof(datatype); \ bIsDirty = true; \ } \ else \ { \ Write( (char*)&value, sizeof(datatype) ); \ } \ // class SvLockBytes void SvLockBytes::close() { if (m_bOwner) delete m_pStream; m_pStream = 0; } TYPEINIT0(SvLockBytes); // virtual ErrCode SvLockBytes::ReadAt(sal_uInt64 const nPos, void * pBuffer, sal_Size nCount, sal_Size * pRead) const { if (!m_pStream) { OSL_FAIL("SvLockBytes::ReadAt(): Bad stream"); return ERRCODE_NONE; } m_pStream->Seek(nPos); sal_Size nTheRead = m_pStream->Read(pBuffer, nCount); if (pRead) *pRead = nTheRead; return m_pStream->GetErrorCode(); } // virtual ErrCode SvLockBytes::WriteAt(sal_uInt64 const nPos, const void * pBuffer, sal_Size nCount, sal_Size * pWritten) { if (!m_pStream) { OSL_FAIL("SvLockBytes::WriteAt(): Bad stream"); return ERRCODE_NONE; } m_pStream->Seek(nPos); sal_Size nTheWritten = m_pStream->Write(pBuffer, nCount); if (pWritten) *pWritten = nTheWritten; return m_pStream->GetErrorCode(); } // virtual ErrCode SvLockBytes::Flush() const { if (!m_pStream) { OSL_FAIL("SvLockBytes::Flush(): Bad stream"); return ERRCODE_NONE; } m_pStream->Flush(); return m_pStream->GetErrorCode(); } // virtual ErrCode SvLockBytes::SetSize(sal_uInt64 const nSize) { if (!m_pStream) { OSL_FAIL("SvLockBytes::SetSize(): Bad stream"); return ERRCODE_NONE; } m_pStream->SetStreamSize(nSize); return m_pStream->GetErrorCode(); } ErrCode SvLockBytes::Stat(SvLockBytesStat * pStat, SvLockBytesStatFlag) const { if (!m_pStream) { OSL_FAIL("SvLockBytes::Stat(): Bad stream"); return ERRCODE_NONE; } if (pStat) { sal_uInt64 const nPos = m_pStream->Tell(); pStat->nSize = m_pStream->Seek(STREAM_SEEK_TO_END); m_pStream->Seek(nPos); } return ERRCODE_NONE; } // class SvOpenLockBytes TYPEINIT1(SvOpenLockBytes, SvLockBytes); // class SvAsyncLockBytes TYPEINIT1(SvAsyncLockBytes, SvOpenLockBytes); // virtual ErrCode SvAsyncLockBytes::ReadAt(sal_uInt64 const nPos, void * pBuffer, sal_Size nCount, sal_Size * pRead) const { if (m_bTerminated) return SvOpenLockBytes::ReadAt(nPos, pBuffer, nCount, pRead); else { sal_Size nTheCount = std::min(nPos < m_nSize ? m_nSize - nPos : 0, nCount); ErrCode nError = SvOpenLockBytes::ReadAt(nPos, pBuffer, nTheCount, pRead); return !nCount || nTheCount == nCount || nError ? nError : ERRCODE_IO_PENDING; } } // virtual ErrCode SvAsyncLockBytes::WriteAt(sal_uInt64 const nPos, const void * pBuffer, sal_Size nCount, sal_Size * pWritten) { if (m_bTerminated) return SvOpenLockBytes::WriteAt(nPos, pBuffer, nCount, pWritten); else { sal_Size nTheCount = std::min(nPos < m_nSize ? m_nSize - nPos : 0, nCount); ErrCode nError = SvOpenLockBytes::WriteAt(nPos, pBuffer, nTheCount, pWritten); return !nCount || nTheCount == nCount || nError ? nError : ERRCODE_IO_PENDING; } } // virtual ErrCode SvAsyncLockBytes::FillAppend(const void * pBuffer, sal_Size nCount, sal_Size * pWritten) { sal_Size nTheWritten; ErrCode nError = SvOpenLockBytes::WriteAt(m_nSize, pBuffer, nCount, &nTheWritten); if (!nError) m_nSize += nTheWritten; if (pWritten) *pWritten = nTheWritten; return nError; } // virtual sal_uInt64 SvAsyncLockBytes::Seek(sal_uInt64 const nPos) { // check if a truncated STREAM_SEEK_TO_END was passed assert(nPos != (sal_uInt64)(sal_uInt32)STREAM_SEEK_TO_END); if (nPos != STREAM_SEEK_TO_END) m_nSize = nPos; return m_nSize; } // class SvStream sal_Size SvStream::GetData( void* pData, sal_Size nSize ) { if( !GetError() ) { DBG_ASSERT( xLockBytes.Is(), "pure virtual function" ); sal_Size nRet; nError = xLockBytes->ReadAt(m_nActPos, pData, nSize, &nRet); m_nActPos += nRet; return nRet; } else return 0; } sal_Size SvStream::PutData( const void* pData, sal_Size nSize ) { if( !GetError() ) { DBG_ASSERT( xLockBytes.Is(), "pure virtual function" ); sal_Size nRet; nError = xLockBytes->WriteAt(m_nActPos, pData, nSize, &nRet); m_nActPos += nRet; return nRet; } else return 0; } sal_uInt64 SvStream::SeekPos(sal_uInt64 const nPos) { // check if a truncated STREAM_SEEK_TO_END was passed assert(nPos != (sal_uInt64)(sal_uInt32)STREAM_SEEK_TO_END); if( !GetError() && nPos == STREAM_SEEK_TO_END ) { DBG_ASSERT( xLockBytes.Is(), "pure virtual function" ); SvLockBytesStat aStat; xLockBytes->Stat( &aStat, SVSTATFLAG_DEFAULT ); m_nActPos = aStat.nSize; } else m_nActPos = nPos; return m_nActPos; } void SvStream::FlushData() { if( !GetError() ) { DBG_ASSERT( xLockBytes.Is(), "pure virtual function" ); nError = xLockBytes->Flush(); } } void SvStream::SetSize(sal_uInt64 const nSize) { DBG_ASSERT( xLockBytes.Is(), "pure virtual function" ); nError = xLockBytes->SetSize( nSize ); } void SvStream::ImpInit() { m_nActPos = 0; nCompressMode = COMPRESSMODE_NONE; eStreamCharSet = osl_getThreadTextEncoding(); nCryptMask = 0; bIsEof = false; #if defined UNX eLineDelimiter = LINEEND_LF; // UNIX-Format #else eLineDelimiter = LINEEND_CRLF; // DOS-Format #endif SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); m_nBufFilePos = 0; nBufActualPos = 0; bIsDirty = false; bIsConsistent = true; bIsWritable = true; pRWBuf = 0; pBufPos = 0; nBufSize = 0; nBufActualLen = 0; bIoRead = false; bIoWrite = false; nBufFree = 0; eStreamMode = 0; nVersion = 0; ClearError(); } SvStream::SvStream( SvLockBytes* pLockBytesP ) { ImpInit(); xLockBytes = pLockBytesP; if( pLockBytesP ) { const SvStream* pStrm = pLockBytesP->GetStream(); if( pStrm ) { SetError( pStrm->GetErrorCode() ); } } SetBufferSize( 256 ); } SvStream::SvStream() { ImpInit(); } SvStream::~SvStream() { if ( xLockBytes.Is() ) Flush(); if( pRWBuf ) delete[] pRWBuf; } void SvStream::ClearError() { bIsEof = false; nError = SVSTREAM_OK; } void SvStream::SetError( sal_uInt32 nErrorCode ) { if ( nError == SVSTREAM_OK ) nError = nErrorCode; } void SvStream::SetNumberFormatInt( sal_uInt16 nNewFormat ) { nNumberFormatInt = nNewFormat; bSwap = false; #ifdef OSL_BIGENDIAN if( nNumberFormatInt == NUMBERFORMAT_INT_LITTLEENDIAN ) bSwap = true; #else if( nNumberFormatInt == NUMBERFORMAT_INT_BIGENDIAN ) bSwap = true; #endif } void SvStream::SetBufferSize( sal_uInt16 nBufferSize ) { sal_uInt64 const nActualFilePos = Tell(); bool bDontSeek = (pRWBuf == 0); if( bIsDirty && bIsConsistent && bIsWritable ) // due to Windows NT: Access denied Flush(); if( nBufSize ) { delete[] pRWBuf; m_nBufFilePos += nBufActualPos; } pRWBuf = 0; nBufActualLen = 0; nBufActualPos = 0; nBufSize = nBufferSize; if( nBufSize ) pRWBuf = new sal_uInt8[ nBufSize ]; bIsConsistent = true; pBufPos = pRWBuf; bIoRead = bIoWrite = false; if( !bDontSeek ) SeekPos( nActualFilePos ); } void SvStream::ClearBuffer() { nBufActualLen = 0; nBufActualPos = 0; m_nBufFilePos = 0; pBufPos = pRWBuf; bIsDirty = false; bIsConsistent = true; bIoRead = bIoWrite = false; bIsEof = false; } void SvStream::ResetError() { ClearError(); } bool SvStream::ReadByteStringLine( OUString& rStr, rtl_TextEncoding eSrcCharSet, sal_Int32 nMaxBytesToRead ) { OString aStr; bool bRet = ReadLine( aStr, nMaxBytesToRead); rStr = OStringToOUString(aStr, eSrcCharSet); return bRet; } bool SvStream::ReadLine( OString& rStr, sal_Int32 nMaxBytesToRead ) { sal_Char buf[256+1]; bool bEnd = false; sal_uInt64 nOldFilePos = Tell(); sal_Char c = 0; sal_Size nTotalLen = 0; OStringBuffer aBuf(4096); while( !bEnd && !GetError() ) // Don't test for EOF as we // are reading block-wise! { sal_uInt16 nLen = (sal_uInt16)Read( buf, sizeof(buf)-1 ); if ( !nLen ) { if ( aBuf.isEmpty() ) { // Exit on first block-read error bIsEof = true; rStr = OString(); return false; } else break; } sal_uInt16 j, n; for( j = n = 0; j < nLen ; ++j ) { c = buf[j]; if ( c == '\n' || c == '\r' ) { bEnd = true; break; } if ( n < j ) buf[n] = c; ++n; } nTotalLen += j; if (nTotalLen > static_cast(nMaxBytesToRead)) { n -= nTotalLen - nMaxBytesToRead; nTotalLen = nMaxBytesToRead; bEnd = true; } if ( n ) aBuf.append(buf, n); } if ( !bEnd && !GetError() && !aBuf.isEmpty() ) bEnd = true; nOldFilePos += nTotalLen; if( Tell() > nOldFilePos ) nOldFilePos++; Seek( nOldFilePos ); // Seek pointer due to BlockRead above if ( bEnd && (c=='\r' || c=='\n') ) // Special treatment for DOS files { char cTemp; sal_Size nLen = Read((char*)&cTemp , sizeof(cTemp) ); if ( nLen ) { if( cTemp == c || (cTemp != '\n' && cTemp != '\r') ) Seek( nOldFilePos ); } } if ( bEnd ) bIsEof = false; rStr = aBuf.makeStringAndClear(); return bEnd; } bool SvStream::ReadUniStringLine( OUString& rStr, sal_Int32 nMaxCodepointsToRead ) { sal_Unicode buf[256+1]; bool bEnd = false; sal_uInt64 nOldFilePos = Tell(); sal_Unicode c = 0; sal_Size nTotalLen = 0; DBG_ASSERT( sizeof(sal_Unicode) == sizeof(sal_uInt16), "ReadUniStringLine: swapping sizeof(sal_Unicode) not implemented" ); OUStringBuffer aBuf(4096); while( !bEnd && !GetError() ) // Don't test for EOF as we // are reading block-wise! { sal_uInt16 nLen = (sal_uInt16)Read( (char*)buf, sizeof(buf)-sizeof(sal_Unicode) ); nLen /= sizeof(sal_Unicode); if ( !nLen ) { if ( aBuf.isEmpty() ) { // exit on first BlockRead error bIsEof = true; rStr = OUString(); return false; } else break; } sal_uInt16 j, n; for( j = n = 0; j < nLen ; ++j ) { if ( bSwap ) SwapUShort( buf[n] ); c = buf[j]; if ( c == '\n' || c == '\r' ) { bEnd = true; break; } // erAck 26.02.01: Old behavior was no special treatment of '\0' // character here, but a following rStr+=c did ignore it. Is this // really intended? Or should a '\0' better terminate a line? // The nOldFilePos stuff wasn't correct then anyways. if ( c ) { if ( n < j ) buf[n] = c; ++n; } } nTotalLen += j; if (nTotalLen > static_cast(nMaxCodepointsToRead)) { n -= nTotalLen - nMaxCodepointsToRead; nTotalLen = nMaxCodepointsToRead; bEnd = true; } if ( n ) aBuf.append( buf, n ); } if ( !bEnd && !GetError() && !aBuf.isEmpty() ) bEnd = true; nOldFilePos += nTotalLen * sizeof(sal_Unicode); if( Tell() > nOldFilePos ) nOldFilePos += sizeof(sal_Unicode); Seek( nOldFilePos ); // seek due to BlockRead above if ( bEnd && (c=='\r' || c=='\n') ) // special treatment for DOS files { sal_Unicode cTemp; Read( (char*)&cTemp, sizeof(cTemp) ); if ( bSwap ) SwapUShort( cTemp ); if( cTemp == c || (cTemp != '\n' && cTemp != '\r') ) Seek( nOldFilePos ); } if ( bEnd ) bIsEof = false; rStr = aBuf.makeStringAndClear(); return bEnd; } bool SvStream::ReadUniOrByteStringLine( OUString& rStr, rtl_TextEncoding eSrcCharSet, sal_Int32 nMaxCodepointsToRead ) { if ( eSrcCharSet == RTL_TEXTENCODING_UNICODE ) return ReadUniStringLine( rStr, nMaxCodepointsToRead ); else return ReadByteStringLine( rStr, eSrcCharSet, nMaxCodepointsToRead ); } OString read_zeroTerminated_uInt8s_ToOString(SvStream& rStream) { OStringBuffer aOutput(256); sal_Char buf[ 256 + 1 ]; bool bEnd = false; sal_uInt64 nFilePos = rStream.Tell(); while( !bEnd && !rStream.GetError() ) { sal_Size nLen = rStream.Read(buf, sizeof(buf)-1); if (!nLen) break; sal_Size nReallyRead = nLen; const sal_Char* pPtr = buf; while (nLen && *pPtr) ++pPtr, --nLen; bEnd = ( nReallyRead < sizeof(buf)-1 ) // read less than attempted to read || ( ( nLen > 0 ) // OR it is inside the block we read && ( 0 == *pPtr ) // AND found a string terminator ); aOutput.append(buf, pPtr - buf); } nFilePos += aOutput.getLength(); if (rStream.Tell() > nFilePos) rStream.Seek(nFilePos+1); // seek due to FileRead above return aOutput.makeStringAndClear(); } OUString read_zeroTerminated_uInt8s_ToOUString(SvStream& rStream, rtl_TextEncoding eEnc) { return OStringToOUString( read_zeroTerminated_uInt8s_ToOString(rStream), eEnc); } /** Attempt to write a prefixed sequence of nUnits 16bit units from an OUString, returned value is number of bytes written */ sal_Size write_uInt16s_FromOUString(SvStream& rStrm, const OUString& rStr, sal_Size nUnits) { DBG_ASSERT( sizeof(sal_Unicode) == sizeof(sal_uInt16), "write_uInt16s_FromOUString: swapping sizeof(sal_Unicode) not implemented" ); sal_Size nWritten; if (!rStrm.IsEndianSwap()) nWritten = rStrm.Write( (char*)rStr.getStr(), nUnits * sizeof(sal_Unicode) ); else { sal_Size nLen = nUnits; sal_Unicode aBuf[384]; sal_Unicode* const pTmp = ( nLen > 384 ? new sal_Unicode[nLen] : aBuf); memcpy( pTmp, rStr.getStr(), nLen * sizeof(sal_Unicode) ); sal_Unicode* p = pTmp; const sal_Unicode* const pStop = pTmp + nLen; while ( p < pStop ) { SwapUShort( *p ); p++; } nWritten = rStrm.Write( (char*)pTmp, nLen * sizeof(sal_Unicode) ); if ( pTmp != aBuf ) delete [] pTmp; } return nWritten; } bool SvStream::WriteUnicodeOrByteText( const OUString& rStr, rtl_TextEncoding eDestCharSet ) { if ( eDestCharSet == RTL_TEXTENCODING_UNICODE ) { write_uInt16s_FromOUString(*this, rStr, rStr.getLength()); return nError == SVSTREAM_OK; } else { OString aStr(OUStringToOString(rStr, eDestCharSet)); write_uInt8s_FromOString(*this, aStr, aStr.getLength()); return nError == SVSTREAM_OK; } } bool SvStream::WriteByteStringLine( const OUString& rStr, rtl_TextEncoding eDestCharSet ) { return WriteLine(OUStringToOString(rStr, eDestCharSet)); } bool SvStream::WriteLine(const OString& rStr) { Write(rStr.getStr(), rStr.getLength()); endl(*this); return nError == SVSTREAM_OK; } bool SvStream::WriteUniOrByteChar( sal_Unicode ch, rtl_TextEncoding eDestCharSet ) { if ( eDestCharSet == RTL_TEXTENCODING_UNICODE ) WriteChar(ch); else { OString aStr(&ch, 1, eDestCharSet); Write(aStr.getStr(), aStr.getLength()); } return nError == SVSTREAM_OK; } bool SvStream::StartWritingUnicodeText() { SetEndianSwap( false ); // write native format // BOM, Byte Order Mark, U+FEFF, see // http://www.unicode.org/faq/utf_bom.html#BOM // Upon read: 0xfeff(-257) => no swap; 0xfffe(-2) => swap WriteUInt16( 0xfeff ); return nError == SVSTREAM_OK; } bool SvStream::StartReadingUnicodeText( rtl_TextEncoding eReadBomCharSet ) { if (!( eReadBomCharSet == RTL_TEXTENCODING_DONTKNOW || eReadBomCharSet == RTL_TEXTENCODING_UNICODE || eReadBomCharSet == RTL_TEXTENCODING_UTF8)) return true; // nothing to read bool bTryUtf8 = false; sal_uInt16 nFlag; sal_sSize nBack = sizeof(nFlag); this->ReadUInt16( nFlag ); switch ( nFlag ) { case 0xfeff : // native UTF-16 if ( eReadBomCharSet == RTL_TEXTENCODING_DONTKNOW || eReadBomCharSet == RTL_TEXTENCODING_UNICODE) nBack = 0; break; case 0xfffe : // swapped UTF-16 if ( eReadBomCharSet == RTL_TEXTENCODING_DONTKNOW || eReadBomCharSet == RTL_TEXTENCODING_UNICODE) { SetEndianSwap( !bSwap ); nBack = 0; } break; case 0xefbb : if (nNumberFormatInt == NUMBERFORMAT_INT_BIGENDIAN && (eReadBomCharSet == RTL_TEXTENCODING_DONTKNOW || eReadBomCharSet == RTL_TEXTENCODING_UTF8)) bTryUtf8 = true; break; case 0xbbef : if (nNumberFormatInt == NUMBERFORMAT_INT_LITTLEENDIAN && (eReadBomCharSet == RTL_TEXTENCODING_DONTKNOW || eReadBomCharSet == RTL_TEXTENCODING_UTF8)) bTryUtf8 = true; break; default: ; // nothing } if (bTryUtf8) { unsigned char nChar; nBack += sizeof(nChar); this->ReadUChar( nChar ); if (nChar == 0xbf) nBack = 0; // it is UTF-8 } if (nBack) SeekRel( -nBack ); // no BOM, pure data return nError == SVSTREAM_OK; } sal_uInt64 SvStream::SeekRel(sal_Int64 const nPos) { sal_uInt64 nActualPos = Tell(); if ( nPos >= 0 ) { if (SAL_MAX_UINT64 - nActualPos > static_cast(nPos)) nActualPos += nPos; } else { sal_uInt64 const nAbsPos = static_cast(-nPos); if ( nActualPos >= nAbsPos ) nActualPos -= nAbsPos; } pBufPos = pRWBuf + nActualPos; return Seek( nActualPos ); } SvStream& SvStream::ReadUInt16(sal_uInt16& r) { sal_uInt16 n = 0; READNUMBER_WITHOUT_SWAP(sal_uInt16, n) if (good()) { if (bSwap) SwapUShort(n); r = n; } return *this; } SvStream& SvStream::ReadUInt32(sal_uInt32& r) { sal_uInt32 n = 0; READNUMBER_WITHOUT_SWAP(sal_uInt32, n) if (good()) { if (bSwap) SwapULong(n); r = n; } return *this; } SvStream& SvStream::ReadUInt64(sal_uInt64& r) { sal_uInt64 n = 0; READNUMBER_WITHOUT_SWAP(sal_uInt64, n) if (good()) { if (bSwap) SwapUInt64(n); r = n; } return *this; } SvStream& SvStream::ReadInt16(sal_Int16& r) { sal_Int16 n = 0; READNUMBER_WITHOUT_SWAP(sal_Int16, n) if (good()) { if (bSwap) SwapShort(n); r = n; } return *this; } SvStream& SvStream::ReadInt32(sal_Int32& r) { sal_Int32 n = 0; READNUMBER_WITHOUT_SWAP(sal_Int32, n) if (good()) { if (bSwap) SwapLongInt(n); r = n; } return *this; } SvStream& SvStream::ReadInt64(sal_Int64& r) { sal_Int64 n = 0; READNUMBER_WITHOUT_SWAP(sal_Int64, n) if (good()) { if (bSwap) SwapInt64(n); r = n; } return *this; } SvStream& SvStream::ReadSChar( signed char& r ) { if( (bIoRead || !bIsConsistent) && sizeof(signed char) <= nBufFree ) { r = *pBufPos; nBufActualPos += sizeof(signed char); pBufPos += sizeof(signed char); nBufFree -= sizeof(signed char); } else Read( (char*)&r, sizeof(signed char) ); return *this; } // Special treatment for Chars due to PutBack SvStream& SvStream::ReadChar( char& r ) { if( (bIoRead || !bIsConsistent) && sizeof(char) <= nBufFree ) { r = *pBufPos; nBufActualPos += sizeof(char); pBufPos += sizeof(char); nBufFree -= sizeof(char); } else Read( (char*)&r, sizeof(char) ); return *this; } SvStream& SvStream::ReadUChar( unsigned char& r ) { if( (bIoRead || !bIsConsistent) && sizeof(char) <= nBufFree ) { r = *pBufPos; nBufActualPos += sizeof(char); pBufPos += sizeof(char); nBufFree -= sizeof(char); } else Read( (char*)&r, sizeof(char) ); return *this; } SvStream& SvStream::ReadCharAsBool( bool& r ) { if( (bIoRead || !bIsConsistent) && sizeof(char) <= nBufFree ) { SAL_WARN_IF( *pBufPos > 1, "tools.stream", unsigned(*pBufPos) << " not 0/1"); r = *pBufPos != 0; nBufActualPos += sizeof(char); pBufPos += sizeof(char); nBufFree -= sizeof(char); } else { unsigned char c; if (Read(&c, 1) == 1) { SAL_WARN_IF(c > 1, "tools.stream", unsigned(c) << " not 0/1"); r = c != 0; } } return *this; } SvStream& SvStream::ReadFloat(float& r) { float n = 0; READNUMBER_WITHOUT_SWAP(float, n) if (good()) { #if defined UNX if (bSwap) SwapFloat(n); #endif r = n; } return *this; } SvStream& SvStream::ReadDouble(double& r) { double n = 0; READNUMBER_WITHOUT_SWAP(double, n) if (good()) { #if defined UNX if (bSwap) SwapDouble(n); #endif r = n; } return *this; } SvStream& SvStream::ReadStream( SvStream& rStream ) { const sal_uInt32 cBufLen = 0x8000; char* pBuf = new char[ cBufLen ]; sal_uInt32 nCount; do { nCount = Read( pBuf, cBufLen ); rStream.Write( pBuf, nCount ); } while( nCount == cBufLen ); delete[] pBuf; return *this; } SvStream& SvStream::WriteUInt16( sal_uInt16 v ) { if( bSwap ) SwapUShort(v); WRITENUMBER_WITHOUT_SWAP(sal_uInt16,v) return *this; } SvStream& SvStream::WriteUInt32( sal_uInt32 v ) { if( bSwap ) SwapULong(v); WRITENUMBER_WITHOUT_SWAP(sal_uInt32,v) return *this; } SvStream& SvStream::WriteUInt64( sal_uInt64 v ) { if( bSwap ) SwapUInt64(v); WRITENUMBER_WITHOUT_SWAP(sal_uInt64,v) return *this; } SvStream& SvStream::WriteInt16( sal_Int16 v ) { if( bSwap ) SwapShort(v); WRITENUMBER_WITHOUT_SWAP(sal_Int16,v) return *this; } SvStream& SvStream::WriteInt32( sal_Int32 v ) { if( bSwap ) SwapLongInt(v); WRITENUMBER_WITHOUT_SWAP(sal_Int32,v) return *this; } SvStream& SvStream::WriteInt64 (sal_Int64 v) { if( bSwap ) SwapInt64(v); WRITENUMBER_WITHOUT_SWAP(sal_Int64,v) return *this; } SvStream& SvStream::WriteSChar( signed char v ) { //SDO if(bIoWrite && sizeof(signed char) <= nBufFree ) { *pBufPos = v; pBufPos++; // sizeof(char); nBufActualPos++; if( nBufActualPos > nBufActualLen ) // Append ? nBufActualLen = nBufActualPos; nBufFree--; // = sizeof(char); bIsDirty = true; } else Write( (char*)&v, sizeof(signed char) ); return *this; } // Special treatment for Chars due to PutBack SvStream& SvStream::WriteChar( char v ) { //SDO if(bIoWrite && sizeof(char) <= nBufFree ) { *pBufPos = v; pBufPos++; // sizeof(char); nBufActualPos++; if( nBufActualPos > nBufActualLen ) // Append ? nBufActualLen = nBufActualPos; nBufFree--; // = sizeof(char); bIsDirty = true; } else Write( (char*)&v, sizeof(char) ); return *this; } SvStream& SvStream::WriteUChar( unsigned char v ) { //SDO if(bIoWrite && sizeof(char) <= nBufFree ) { *(unsigned char*)pBufPos = v; pBufPos++; // = sizeof(char); nBufActualPos++; // = sizeof(char); if( nBufActualPos > nBufActualLen ) // Append ? nBufActualLen = nBufActualPos; nBufFree--; bIsDirty = true; } else Write( (char*)&v, sizeof(char) ); return *this; } SvStream& SvStream::WriteUInt8( sal_uInt8 v ) { return WriteUChar(v); } SvStream& SvStream::WriteUnicode( sal_Unicode v ) { return WriteUInt16(v); } SvStream& SvStream::WriteFloat( float v ) { #ifdef UNX if( bSwap ) SwapFloat(v); #endif WRITENUMBER_WITHOUT_SWAP(float,v) return *this; } SvStream& SvStream::WriteDouble ( const double& r ) { #if defined UNX if( bSwap ) { double nHelp = r; SwapDouble(nHelp); WRITENUMBER_WITHOUT_SWAP(double,nHelp) return *this; } else #endif { WRITENUMBER_WITHOUT_SWAP(double,r); } return *this; } SvStream& SvStream::WriteCharPtr( const char* pBuf ) { Write( pBuf, strlen( pBuf ) ); return *this; } SvStream& SvStream::WriteStream( SvStream& rStream ) { const sal_uInt32 cBufLen = 0x8000; char* pBuf = new char[ cBufLen ]; sal_uInt32 nCount; do { nCount = rStream.Read( pBuf, cBufLen ); Write( pBuf, nCount ); } while( nCount == cBufLen ); delete[] pBuf; return *this; } OUString SvStream::ReadUniOrByteString( rtl_TextEncoding eSrcCharSet ) { // read UTF-16 string directly from stream ? if (eSrcCharSet == RTL_TEXTENCODING_UNICODE) return read_uInt32_lenPrefixed_uInt16s_ToOUString(*this); return read_uInt16_lenPrefixed_uInt8s_ToOUString(*this, eSrcCharSet); } SvStream& SvStream::WriteUniOrByteString( const OUString& rStr, rtl_TextEncoding eDestCharSet ) { // write UTF-16 string directly into stream ? if (eDestCharSet == RTL_TEXTENCODING_UNICODE) write_uInt32_lenPrefixed_uInt16s_FromOUString(*this, rStr); else write_uInt16_lenPrefixed_uInt8s_FromOUString(*this, rStr, eDestCharSet); return *this; } sal_Size SvStream::Read( void* pData, sal_Size nCount ) { sal_Size nSaveCount = nCount; if( !bIsConsistent ) RefreshBuffer(); if( !pRWBuf ) { nCount = GetData( (char*)pData,nCount); if( nCryptMask ) EncryptBuffer(pData, nCount); m_nBufFilePos += nCount; } else { // check if block is completely within buffer bIoRead = true; bIoWrite = false; if( nCount <= (sal_Size)(nBufActualLen - nBufActualPos ) ) { // => yes memcpy(pData, pBufPos, (size_t) nCount); nBufActualPos = nBufActualPos + (sal_uInt16)nCount; pBufPos += nCount; nBufFree = nBufFree - (sal_uInt16)nCount; } else { if( bIsDirty ) // Does stream require a flush? { SeekPos(m_nBufFilePos); if( nCryptMask ) CryptAndWriteBuffer(pRWBuf, nBufActualLen); else PutData( pRWBuf, nBufActualLen ); bIsDirty = false; } // Does data block fit into buffer? if( nCount > nBufSize ) { // => No! Thus read directly // into target area without using the buffer bIoRead = false; SeekPos(m_nBufFilePos + nBufActualPos); nBufActualLen = 0; pBufPos = pRWBuf; nCount = GetData( (char*)pData, nCount ); if( nCryptMask ) EncryptBuffer(pData, nCount); m_nBufFilePos += nCount; m_nBufFilePos += nBufActualPos; nBufActualPos = 0; } else { // => Yes. Fill buffer first, then copy to target area m_nBufFilePos += nBufActualPos; SeekPos(m_nBufFilePos); // TODO: Typecast before GetData, sal_uInt16 nCountTmp sal_Size nCountTmp = GetData( pRWBuf, nBufSize ); if( nCryptMask ) EncryptBuffer(pRWBuf, nCountTmp); nBufActualLen = (sal_uInt16)nCountTmp; if( nCount > nCountTmp ) { nCount = nCountTmp; // trim count back, EOF see below } memcpy( pData, pRWBuf, (size_t)nCount ); nBufActualPos = (sal_uInt16)nCount; pBufPos = pRWBuf + nCount; } } } bIsEof = false; nBufFree = nBufActualLen - nBufActualPos; if( nCount != nSaveCount && nError != ERRCODE_IO_PENDING ) bIsEof = true; if( nCount == nSaveCount && nError == ERRCODE_IO_PENDING ) nError = ERRCODE_NONE; return nCount; } sal_Size SvStream::Write( const void* pData, sal_Size nCount ) { if( !nCount ) return 0; if( !bIsWritable ) { SetError( ERRCODE_IO_CANTWRITE ); return 0; } if( !bIsConsistent ) RefreshBuffer(); // Remove changes in buffer through PutBack if( !pRWBuf ) { if( nCryptMask ) nCount = CryptAndWriteBuffer( pData, nCount ); else nCount = PutData( (char*)pData, nCount ); m_nBufFilePos += nCount; return nCount; } bIoRead = false; bIoWrite = true; if( nCount <= (sal_Size)(nBufSize - nBufActualPos) ) { memcpy( pBufPos, pData, (size_t)nCount ); nBufActualPos = nBufActualPos + (sal_uInt16)nCount; // Update length if buffer was updated if( nBufActualPos > nBufActualLen ) nBufActualLen = nBufActualPos; pBufPos += nCount; bIsDirty = true; } else { // Does stream require flushing? if( bIsDirty ) { SeekPos(m_nBufFilePos); if( nCryptMask ) CryptAndWriteBuffer( pRWBuf, (sal_Size)nBufActualLen ); else PutData( pRWBuf, nBufActualLen ); bIsDirty = false; } // Does data block fit into buffer? if( nCount > nBufSize ) { bIoWrite = false; m_nBufFilePos += nBufActualPos; nBufActualLen = 0; nBufActualPos = 0; pBufPos = pRWBuf; SeekPos(m_nBufFilePos); if( nCryptMask ) nCount = CryptAndWriteBuffer( pData, nCount ); else nCount = PutData( (char*)pData, nCount ); m_nBufFilePos += nCount; } else { // Copy block to buffer memcpy( pRWBuf, pData, (size_t)nCount ); // Mind the order! m_nBufFilePos += nBufActualPos; nBufActualPos = (sal_uInt16)nCount; pBufPos = pRWBuf + nCount; nBufActualLen = (sal_uInt16)nCount; bIsDirty = true; } } nBufFree = nBufSize - nBufActualPos; return nCount; } sal_uInt64 SvStream::Seek(sal_uInt64 const nFilePos) { bIoRead = bIoWrite = false; bIsEof = false; if( !pRWBuf ) { m_nBufFilePos = SeekPos( nFilePos ); DBG_ASSERT(Tell() == m_nBufFilePos,"Out Of Sync!"); return m_nBufFilePos; } // Is seek position within buffer? if (nFilePos >= m_nBufFilePos && nFilePos <= (m_nBufFilePos + nBufActualLen)) { nBufActualPos = (sal_uInt16)(nFilePos - m_nBufFilePos); pBufPos = pRWBuf + nBufActualPos; // Update nBufFree to avoid crash upon PutBack nBufFree = nBufActualLen - nBufActualPos; } else { if( bIsDirty && bIsConsistent) { SeekPos(m_nBufFilePos); if( nCryptMask ) CryptAndWriteBuffer( pRWBuf, nBufActualLen ); else PutData( pRWBuf, nBufActualLen ); bIsDirty = false; } nBufActualLen = 0; nBufActualPos = 0; pBufPos = pRWBuf; m_nBufFilePos = SeekPos( nFilePos ); } #ifdef OV_DEBUG { sal_uInt64 nDebugTemp = m_nBufFilePos + nBufActualPos; DBG_ASSERT(Tell()==nDebugTemp,"Sync?"); } #endif return m_nBufFilePos + nBufActualPos; } //STREAM_SEEK_TO_END in the some of the Seek backends is special cased to be //efficient, in others e.g. SotStorageStream it's really horribly slow, and in //those this should be overridden sal_uInt64 SvStream::remainingSize() { sal_uInt64 const nCurr = Tell(); sal_uInt64 const nEnd = Seek(STREAM_SEEK_TO_END); sal_uInt64 nMaxAvailable = nEnd-nCurr; Seek(nCurr); return nMaxAvailable; } void SvStream::Flush() { if( bIsDirty && bIsConsistent ) { SeekPos(m_nBufFilePos); if( nCryptMask ) CryptAndWriteBuffer( pRWBuf, (sal_Size)nBufActualLen ); else if( PutData( pRWBuf, nBufActualLen ) != nBufActualLen ) SetError( SVSTREAM_WRITE_ERROR ); bIsDirty = false; } if( bIsWritable ) FlushData(); } void SvStream::RefreshBuffer() { if( bIsDirty && bIsConsistent ) { SeekPos(m_nBufFilePos); if( nCryptMask ) CryptAndWriteBuffer( pRWBuf, (sal_Size)nBufActualLen ); else PutData( pRWBuf, nBufActualLen ); bIsDirty = false; } SeekPos(m_nBufFilePos); nBufActualLen = (sal_uInt16)GetData( pRWBuf, nBufSize ); if( nBufActualLen && nError == ERRCODE_IO_PENDING ) nError = ERRCODE_NONE; if( nCryptMask ) EncryptBuffer(pRWBuf, (sal_Size)nBufActualLen); bIsConsistent = true; bIoRead = bIoWrite = false; } SvStream& SvStream::WriteNumber(sal_Int32 nInt32) { char buffer[12]; sal_Size nLen = sprintf(buffer, "%" SAL_PRIdINT32, nInt32); Write(buffer, nLen); return *this; } SvStream& SvStream::WriteNumber(sal_uInt32 nUInt32) { char buffer[11]; sal_Size nLen = sprintf(buffer, "%" SAL_PRIuUINT32, nUInt32); Write(buffer, nLen); return *this; } #define CRYPT_BUFSIZE 1024 /// Encrypt and write sal_Size SvStream::CryptAndWriteBuffer( const void* pStart, sal_Size nLen) { unsigned char pTemp[CRYPT_BUFSIZE]; unsigned char* pDataPtr = (unsigned char*)pStart; sal_Size nCount = 0; sal_Size nBufCount; unsigned char nMask = nCryptMask; do { if( nLen >= CRYPT_BUFSIZE ) nBufCount = CRYPT_BUFSIZE; else nBufCount = nLen; nLen -= nBufCount; memcpy( pTemp, pDataPtr, (sal_uInt16)nBufCount ); // **** Verschluesseln ***** for ( sal_uInt16 n=0; n < CRYPT_BUFSIZE; n++ ) { unsigned char aCh = pTemp[n]; aCh ^= nMask; SWAPNIBBLES(aCh) pTemp[n] = aCh; } // ************************* nCount += PutData( (char*)pTemp, nBufCount ); pDataPtr += nBufCount; } while ( nLen ); return nCount; } bool SvStream::EncryptBuffer(void* pStart, sal_Size nLen) { unsigned char* pTemp = (unsigned char*)pStart; unsigned char nMask = nCryptMask; for ( sal_Size n=0; n < nLen; n++, pTemp++ ) { unsigned char aCh = *pTemp; SWAPNIBBLES(aCh) aCh ^= nMask; *pTemp = aCh; } return true; } static unsigned char implGetCryptMask(const sal_Char* pStr, sal_Int32 nLen, long nVersion) { unsigned char nCryptMask = 0; if (!nLen) return nCryptMask; if( nVersion <= SOFFICE_FILEFORMAT_31 ) { while( nLen ) { nCryptMask ^= *pStr; pStr++; nLen--; } } else // BugFix #25888# { for( sal_uInt16 i = 0; i < nLen; i++ ) { nCryptMask ^= pStr[i]; if( nCryptMask & 0x80 ) { nCryptMask <<= 1; nCryptMask++; } else nCryptMask <<= 1; } } if( !nCryptMask ) nCryptMask = 67; return nCryptMask; } void SvStream::SetCryptMaskKey(const OString& rCryptMaskKey) { m_aCryptMaskKey = rCryptMaskKey; nCryptMask = implGetCryptMask(m_aCryptMaskKey.getStr(), m_aCryptMaskKey.getLength(), GetVersion()); } void SvStream::SyncSvStream( sal_Size nNewStreamPos ) { ClearBuffer(); SvStream::m_nBufFilePos = nNewStreamPos; } void SvStream::SyncSysStream() { Flush(); SeekPos( Tell() ); } bool SvStream::SetStreamSize(sal_uInt64 const nSize) { #ifdef DBG_UTIL sal_uInt64 nFPos = Tell(); #endif sal_uInt16 nBuf = nBufSize; SetBufferSize( 0 ); SetSize( nSize ); SetBufferSize( nBuf ); DBG_ASSERT(Tell()==nFPos,"SetStreamSize failed"); return (nError == 0); } SvStream& endl( SvStream& rStr ) { LineEnd eDelim = rStr.GetLineDelimiter(); if ( eDelim == LINEEND_CR ) rStr.WriteChar('\r'); else if( eDelim == LINEEND_LF ) rStr.WriteChar('\n'); else rStr.WriteChar('\r').WriteChar('\n'); return rStr; } SvStream& endlu( SvStream& rStrm ) { switch ( rStrm.GetLineDelimiter() ) { case LINEEND_CR : rStrm.WriteUnicode('\r'); break; case LINEEND_LF : rStrm.WriteUnicode('\n'); break; default: rStrm.WriteUnicode('\r').WriteUnicode('\n'); } return rStrm; } SvStream& endlub( SvStream& rStrm ) { if ( rStrm.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE ) return endlu( rStrm ); else return endl( rStrm ); } SvMemoryStream::SvMemoryStream( void* pBuffer, sal_Size bufSize, StreamMode eMode ) { if( eMode & STREAM_WRITE ) bIsWritable = true; else bIsWritable = false; nEndOfData = bufSize; bOwnsData = false; pBuf = (sal_uInt8 *) pBuffer; nResize = 0L; nSize = bufSize; nPos = 0L; SetBufferSize( 0 ); } SvMemoryStream::SvMemoryStream( sal_Size nInitSize, sal_Size nResizeOffset ) { bIsWritable = true; bOwnsData = true; nEndOfData = 0L; nResize = nResizeOffset; nPos = 0; pBuf = 0; if( nResize != 0 && nResize < 16 ) nResize = 16; if( nInitSize && !AllocateMemory( nInitSize ) ) { SetError( SVSTREAM_OUTOFMEMORY ); nSize = 0; } else nSize = nInitSize; SetBufferSize( 64 ); } SvMemoryStream::~SvMemoryStream() { if( pBuf ) { if( bOwnsData ) FreeMemory(); else Flush(); } } const void* SvMemoryStream::GetBuffer() { Flush(); return (const void*)GetData(); } sal_uIntPtr SvMemoryStream::GetSize() { Flush(); sal_uInt64 const nTemp = Tell(); sal_uInt64 const nLength = Seek( STREAM_SEEK_TO_END ); Seek( nTemp ); return nLength; } void* SvMemoryStream::SetBuffer( void* pNewBuf, sal_Size nCount, bool bOwnsDat, sal_Size nEOF ) { void* pResult; SetBufferSize( 0 ); // Buffering in der Basisklasse initialisieren Seek( 0 ); if( bOwnsData ) { pResult = 0; if( pNewBuf != pBuf ) FreeMemory(); } else pResult = pBuf; pBuf = (sal_uInt8 *) pNewBuf; nPos = 0; nSize = nCount; nResize = 0; bOwnsData = bOwnsDat; if( nEOF > nCount ) nEOF = nCount; nEndOfData = nEOF; ResetError(); return pResult; } sal_Size SvMemoryStream::GetData( void* pData, sal_Size nCount ) { sal_Size nMaxCount = nEndOfData-nPos; if( nCount > nMaxCount ) nCount = nMaxCount; memcpy( pData, pBuf+nPos, (size_t)nCount ); nPos += nCount; return nCount; } sal_Size SvMemoryStream::PutData( const void* pData, sal_Size nCount ) { if( GetError() ) return 0L; sal_Size nMaxCount = nSize-nPos; // check for overflow if( nCount > nMaxCount ) { if( nResize == 0 ) { // copy as much as possible nCount = nMaxCount; SetError( SVSTREAM_OUTOFMEMORY ); } else { long nNewResize; if( nSize && nSize > nResize ) nNewResize = nSize; else nNewResize = nResize; if( (nCount-nMaxCount) < nResize ) { // lacking memory is smaller than nResize, // resize accordingly if( !ReAllocateMemory( nNewResize) ) { nCount = 0; SetError( SVSTREAM_WRITE_ERROR ); } } else { // lacking memory is larger than nResize, // resize by (nCoount-nMaxCount) + resize offset if( !ReAllocateMemory( nCount-nMaxCount+nNewResize ) ) { nCount = 0; SetError( SVSTREAM_WRITE_ERROR ); } } } } DBG_ASSERT(pBuf,"Possibly Reallocate failed"); memcpy( pBuf+nPos, pData, (size_t)nCount); nPos += nCount; if( nPos > nEndOfData ) nEndOfData = nPos; return nCount; } sal_uInt64 SvMemoryStream::SeekPos(sal_uInt64 const nNewPos) { // nEndOfData: First position in stream not allowed to read from // nSize: Size of allocated buffer // check if a truncated STREAM_SEEK_TO_END was passed assert(nNewPos != (sal_uInt64)(sal_uInt32)STREAM_SEEK_TO_END); if( nNewPos < nEndOfData ) nPos = nNewPos; else if( nNewPos == STREAM_SEEK_TO_END ) nPos = nEndOfData; else { if( nNewPos >= nSize ) // Does buffer need extension? { if( nResize ) // Is extension possible? { long nDiff = (long)(nNewPos - nSize + 1); nDiff += (long)nResize; ReAllocateMemory( nDiff ); nPos = nNewPos; nEndOfData = nNewPos; } else // Extension not possible, set pos to end of data { // SetError( SVSTREAM_OUTOFMEMORY ); nPos = nEndOfData; } } else // Expand buffer size { nPos = nNewPos; nEndOfData = nNewPos; } } return nPos; } void SvMemoryStream::FlushData() { } void SvMemoryStream::ResetError() { SvStream::ClearError(); } bool SvMemoryStream::AllocateMemory( sal_Size nNewSize ) { pBuf = new sal_uInt8[nNewSize]; return( pBuf != 0 ); } // (using Bozo algorithm) bool SvMemoryStream::ReAllocateMemory( long nDiff ) { bool bRetVal = false; long nTemp = (long)nSize; nTemp += nDiff; sal_Size nNewSize = (sal_Size)nTemp; if( nNewSize ) { sal_uInt8* pNewBuf = new sal_uInt8[nNewSize]; if( pNewBuf ) { bRetVal = true; // Success! if( nNewSize < nSize ) // Are we shrinking? { memcpy( pNewBuf, pBuf, (size_t)nNewSize ); if( nPos > nNewSize ) nPos = 0L; if( nEndOfData >= nNewSize ) nEndOfData = nNewSize-1L; } else { memcpy( pNewBuf, pBuf, (size_t)nSize ); } FreeMemory(); pBuf = pNewBuf; nSize = nNewSize; } } else { bRetVal = true; FreeMemory(); pBuf = 0; nSize = 0; nEndOfData = 0; nPos = 0; } return bRetVal; } void SvMemoryStream::FreeMemory() { delete[] pBuf; } void* SvMemoryStream::SwitchBuffer( sal_Size nInitSize, sal_Size nResizeOffset) { Flush(); if( !bOwnsData ) return 0; Seek( STREAM_SEEK_TO_BEGIN ); void* pRetVal = pBuf; pBuf = 0; nEndOfData = 0L; nResize = nResizeOffset; nPos = 0; if( nResize != 0 && nResize < 16 ) nResize = 16; ResetError(); if( nInitSize && !AllocateMemory(nInitSize) ) { SetError( SVSTREAM_OUTOFMEMORY ); nSize = 0; } else nSize = nInitSize; SetBufferSize( 64 ); return pRetVal; } void SvMemoryStream::SetSize(sal_uInt64 const nNewSize) { long nDiff = (long)nNewSize - (long)nSize; ReAllocateMemory( nDiff ); } SvScriptStream::SvScriptStream(const OUString& rUrl): mpProcess(NULL), mpHandle(NULL) { oslProcessError rc; rc = osl_executeProcess_WithRedirectedIO( rUrl.pData, NULL, 0, osl_Process_HIDDEN, NULL, NULL, NULL, 0, &mpProcess, NULL, &mpHandle, NULL); if (osl_Process_E_None != rc) { mpProcess = NULL; mpHandle = NULL; } } SvScriptStream::~SvScriptStream() { if (mpProcess) { osl_terminateProcess(mpProcess); osl_freeProcessHandle(mpProcess); } if (mpHandle) osl_closeFile(mpHandle); } bool SvScriptStream::ReadLine(OString &rStr, sal_Int32) { rStr = OString(); if (!good()) return false; OStringBuffer sBuf; sal_Char aChar('\n'); sal_uInt64 nBytesRead; while (osl_File_E_None == osl_readFile(mpHandle, &aChar, 1, &nBytesRead) && nBytesRead == 1 && aChar != '\n') { sBuf.append( aChar ); } rStr = sBuf.makeStringAndClear(); if (!rStr.isEmpty()) return true; return false; } bool SvScriptStream::good() const { return mpHandle != NULL; } TYPEINIT0 ( SvDataCopyStream ) void SvDataCopyStream::Assign( const SvDataCopyStream& ) { } //Create a OString of nLen bytes from rStream OString read_uInt8s_ToOString(SvStream& rStrm, sal_Size nLen) { rtl_String *pStr = NULL; if (nLen) { nLen = std::min(nLen, static_cast(SAL_MAX_INT32)); //alloc a (ref-count 1) rtl_String of the desired length. //rtl_String's buffer is uninitialized, except for null termination pStr = rtl_string_alloc(sal::static_int_cast(nLen)); SAL_WARN_IF(!pStr, "tools", "allocation failed"); if (pStr) { sal_Size nWasRead = rStrm.Read(pStr->buffer, nLen); if (nWasRead != nLen) { //on (typically unlikely) short read set length to what we could //read, and null terminate. Excess buffer capacity remains of //course, could create a (true) replacement OString if it matters. pStr->length = sal::static_int_cast(nWasRead); pStr->buffer[pStr->length] = 0; } } } //take ownership of buffer and return, otherwise return empty string return pStr ? OString(pStr, SAL_NO_ACQUIRE) : OString(); } //Create a OUString of nLen sal_Unicodes from rStream OUString read_uInt16s_ToOUString(SvStream& rStrm, sal_Size nLen) { rtl_uString *pStr = NULL; if (nLen) { nLen = std::min(nLen, static_cast(SAL_MAX_INT32)); //alloc a (ref-count 1) rtl_uString of the desired length. //rtl_String's buffer is uninitialized, except for null termination pStr = rtl_uString_alloc(sal::static_int_cast(nLen)); SAL_WARN_IF(!pStr, "tools", "allocation failed"); if (pStr) { sal_Size nWasRead = rStrm.Read(pStr->buffer, nLen*2)/2; if (nWasRead != nLen) { //on (typically unlikely) short read set length to what we could //read, and null terminate. Excess buffer capacity remains of //course, could create a (true) replacement OUString if it matters. pStr->length = sal::static_int_cast(nWasRead); pStr->buffer[pStr->length] = 0; } if (rStrm.IsEndianSwap()) { for (sal_Int32 i = 0; i < pStr->length; ++i) pStr->buffer[i] = OSL_SWAPWORD(pStr->buffer[i]); } } } //take ownership of buffer and return, otherwise return empty string return pStr ? OUString(pStr, SAL_NO_ACQUIRE) : OUString(); } namespace { template T tmpl_convertLineEnd(const T &rIn, LineEnd eLineEnd) { // Determine linebreaks and compute length bool bConvert = false; // Needs conversion sal_Int32 nStrLen = rIn.getLength(); sal_Int32 nLineEndLen = (eLineEnd == LINEEND_CRLF) ? 2 : 1; sal_Int32 nLen = 0; // Target length sal_Int32 i = 0; // Source counter while (i < nStrLen) { // \r or \n causes linebreak if ( (rIn[i] == '\r') || (rIn[i] == '\n') ) { nLen = nLen + nLineEndLen; // If set already, skip expensive test if ( !bConvert ) { // Muessen wir Konvertieren if ( ((eLineEnd != LINEEND_LF) && (rIn[i] == '\n')) || ((eLineEnd == LINEEND_CRLF) && (i+1) < nStrLen && (rIn[i+1] != '\n')) || ((eLineEnd == LINEEND_LF) && ((rIn[i] == '\r') || ((i+1) < nStrLen && rIn[i+1] == '\r'))) || ((eLineEnd == LINEEND_CR) && ((rIn[i] == '\n') || ((i+1) < nStrLen && rIn[i+1] == '\n'))) ) bConvert = true; } // skip char if \r\n or \n\r if ( (i+1) < nStrLen && ((rIn[i+1] == '\r') || (rIn[i+1] == '\n')) && (rIn[i] != rIn[i+1]) ) ++i; } else ++nLen; ++i; } if (!bConvert) return rIn; // convert linebreaks, insert string O aNewData(nLen); i = 0; while (i < nStrLen) { // \r or \n causes linebreak if ( (rIn[i] == '\r') || (rIn[i] == '\n') ) { if ( eLineEnd == LINEEND_CRLF ) { aNewData.append('\r'); aNewData.append('\n'); } else { if ( eLineEnd == LINEEND_CR ) aNewData.append('\r'); else aNewData.append('\n'); } if ( (i+1) < nStrLen && ((rIn[i+1] == '\r') || (rIn[i+1] == '\n')) && (rIn[i] != rIn[i+1]) ) ++i; } else { aNewData.append(rIn[i]); } ++i; } return aNewData.makeStringAndClear(); } } OString convertLineEnd(const OString &rIn, LineEnd eLineEnd) { return tmpl_convertLineEnd(rIn, eLineEnd); } OUString convertLineEnd(const OUString &rIn, LineEnd eLineEnd) { return tmpl_convertLineEnd(rIn, eLineEnd); } sal_Size write_uInt32_lenPrefixed_uInt16s_FromOUString(SvStream& rStrm, const OUString &rStr) { sal_Size nWritten = 0; sal_uInt32 nUnits = std::min(rStr.getLength(), std::numeric_limits::max()); SAL_WARN_IF(static_cast(nUnits) != static_cast(rStr.getLength()), "tools.stream", "string too long for prefix count to fit in output type"); rStrm.WriteUInt32(nUnits); if (rStrm.good()) { nWritten += sizeof(sal_uInt32); nWritten += write_uInt16s_FromOUString(rStrm, rStr, nUnits); } return nWritten; } sal_Size write_uInt16_lenPrefixed_uInt16s_FromOUString(SvStream& rStrm, const OUString &rStr) { sal_Size nWritten = 0; sal_uInt16 nUnits = std::min(rStr.getLength(), std::numeric_limits::max()); SAL_WARN_IF(nUnits != rStr.getLength(), "tools.stream", "string too long for prefix count to fit in output type"); rStrm.WriteUInt16(nUnits); if (rStrm.good()) { nWritten += sizeof(nUnits); nWritten += write_uInt16s_FromOUString(rStrm, rStr, nUnits); } return nWritten; } sal_Size write_uInt16_lenPrefixed_uInt8s_FromOString(SvStream& rStrm, const OString &rStr) { sal_Size nWritten = 0; sal_uInt16 nUnits = std::min(rStr.getLength(), std::numeric_limits::max()); SAL_WARN_IF(static_cast(nUnits) != static_cast(rStr.getLength()), "tools.stream", "string too long for sal_uInt16 count to fit in output type"); rStrm.WriteUInt16( nUnits ); if (rStrm.good()) { nWritten += sizeof(sal_uInt16); nWritten += write_uInt8s_FromOString(rStrm, rStr, nUnits); } return nWritten; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */