17d4bb38fa
This is a follow-up patch of 7710faa45640d25a83136a35044aafdb1b168d88. Change-Id: I1f54cbe5c3170e9a79e11e9b9c1da3791419a4ba
2120 lines
54 KiB
C++
2120 lines
54 KiB
C++
/* -*- 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 <cstddef>
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <ctype.h> // isspace
|
|
#include <stdlib.h> // strtol, _crotl
|
|
|
|
#include "boost/static_assert.hpp"
|
|
|
|
#include <tools/solar.h>
|
|
#include <osl/endian.h>
|
|
|
|
#include <comphelper/string.hxx>
|
|
|
|
#define SWAPNIBBLES(c) \
|
|
unsigned char nSwapTmp=c; \
|
|
nSwapTmp <<= 4; \
|
|
c >>= 4; \
|
|
c |= nSwapTmp;
|
|
|
|
#include <tools/debug.hxx>
|
|
#include <tools/stream.hxx>
|
|
#include <osl/thread.h>
|
|
#include <algorithm>
|
|
|
|
DBG_NAME( Stream )
|
|
|
|
// !!! 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 SwapLong( long& r )
|
|
{ r = OSL_SWAPDWORD(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 SwapLongUInt( unsigned int& 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( sal_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) \
|
|
{\
|
|
int tmp = eIOMode; \
|
|
if( (tmp == STREAM_IO_READ) && 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) \
|
|
{\
|
|
int tmp = eIOMode; \
|
|
if( (tmp==STREAM_IO_WRITE) && 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 = sal_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_Size 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_Size 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_Size 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_Size 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_Size 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_Size 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_Size SvAsyncLockBytes::Seek(sal_Size nPos)
|
|
{
|
|
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( nActPos, pData, nSize, &nRet );
|
|
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( nActPos, pData, nSize, &nRet );
|
|
nActPos += nRet;
|
|
return nRet;
|
|
}
|
|
else return 0;
|
|
}
|
|
|
|
sal_Size SvStream::SeekPos( sal_Size nPos )
|
|
{
|
|
if( !GetError() && nPos == STREAM_SEEK_TO_END )
|
|
{
|
|
DBG_ASSERT( xLockBytes.Is(), "pure virtual function" );
|
|
SvLockBytesStat aStat;
|
|
xLockBytes->Stat( &aStat, SVSTATFLAG_DEFAULT );
|
|
nActPos = aStat.nSize;
|
|
}
|
|
else
|
|
nActPos = nPos;
|
|
return nActPos;
|
|
}
|
|
|
|
void SvStream::FlushData()
|
|
{
|
|
if( !GetError() )
|
|
{
|
|
DBG_ASSERT( xLockBytes.Is(), "pure virtual function" );
|
|
nError = xLockBytes->Flush();
|
|
}
|
|
}
|
|
|
|
void SvStream::SetSize( sal_Size nSize )
|
|
{
|
|
DBG_ASSERT( xLockBytes.Is(), "pure virtual function" );
|
|
nError = xLockBytes->SetSize( nSize );
|
|
}
|
|
|
|
void SvStream::ImpInit()
|
|
{
|
|
nActPos = 0;
|
|
nCompressMode = COMPRESSMODE_NONE;
|
|
eStreamCharSet = osl_getThreadTextEncoding();
|
|
nCryptMask = 0;
|
|
bIsEof = sal_False;
|
|
#if defined UNX
|
|
eLineDelimiter = LINEEND_LF; // UNIX-Format
|
|
#else
|
|
eLineDelimiter = LINEEND_CRLF; // DOS-Format
|
|
#endif
|
|
|
|
SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
|
|
|
|
nBufFilePos = 0;
|
|
nBufActualPos = 0;
|
|
bIsDirty = sal_False;
|
|
bIsConsistent = sal_True;
|
|
bIsWritable = sal_True;
|
|
|
|
pRWBuf = 0;
|
|
pBufPos = 0;
|
|
nBufSize = 0;
|
|
nBufActualLen = 0;
|
|
eIOMode = STREAM_IO_DONTKNOW;
|
|
nBufFree = 0;
|
|
|
|
eStreamMode = 0;
|
|
|
|
nVersion = 0;
|
|
|
|
ClearError();
|
|
}
|
|
|
|
SvStream::SvStream( SvLockBytes* pLockBytesP )
|
|
{
|
|
DBG_CTOR( Stream, NULL );
|
|
|
|
ImpInit();
|
|
xLockBytes = pLockBytesP;
|
|
const SvStream* pStrm;
|
|
if( pLockBytesP ) {
|
|
pStrm = pLockBytesP->GetStream();
|
|
if( pStrm ) {
|
|
SetError( pStrm->GetErrorCode() );
|
|
}
|
|
}
|
|
SetBufferSize( 256 );
|
|
}
|
|
|
|
SvStream::SvStream()
|
|
{
|
|
DBG_CTOR( Stream, NULL );
|
|
|
|
ImpInit();
|
|
}
|
|
|
|
SvStream::~SvStream()
|
|
{
|
|
DBG_DTOR( Stream, NULL );
|
|
|
|
if ( xLockBytes.Is() )
|
|
Flush();
|
|
|
|
if( pRWBuf )
|
|
delete[] pRWBuf;
|
|
}
|
|
|
|
sal_uInt16 SvStream::IsA() const
|
|
{
|
|
return (sal_uInt16)ID_STREAM;
|
|
}
|
|
|
|
void SvStream::ClearError()
|
|
{
|
|
bIsEof = sal_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 = sal_False;
|
|
#ifdef OSL_BIGENDIAN
|
|
if( nNumberFormatInt == NUMBERFORMAT_INT_LITTLEENDIAN )
|
|
bSwap = sal_True;
|
|
#else
|
|
if( nNumberFormatInt == NUMBERFORMAT_INT_BIGENDIAN )
|
|
bSwap = sal_True;
|
|
#endif
|
|
}
|
|
|
|
void SvStream::SetBufferSize( sal_uInt16 nBufferSize )
|
|
{
|
|
sal_Size nActualFilePos = Tell();
|
|
sal_Bool bDontSeek = (sal_Bool)(pRWBuf == 0);
|
|
|
|
if( bIsDirty && bIsConsistent && bIsWritable ) // due to Windows NT: Access denied
|
|
Flush();
|
|
|
|
if( nBufSize )
|
|
{
|
|
delete[] pRWBuf;
|
|
nBufFilePos += nBufActualPos;
|
|
}
|
|
|
|
pRWBuf = 0;
|
|
nBufActualLen = 0;
|
|
nBufActualPos = 0;
|
|
nBufSize = nBufferSize;
|
|
if( nBufSize )
|
|
pRWBuf = new sal_uInt8[ nBufSize ];
|
|
bIsConsistent = sal_True;
|
|
pBufPos = pRWBuf;
|
|
eIOMode = STREAM_IO_DONTKNOW;
|
|
if( !bDontSeek )
|
|
SeekPos( nActualFilePos );
|
|
}
|
|
|
|
void SvStream::ClearBuffer()
|
|
{
|
|
nBufActualLen = 0;
|
|
nBufActualPos = 0;
|
|
nBufFilePos = 0;
|
|
pBufPos = pRWBuf;
|
|
bIsDirty = sal_False;
|
|
bIsConsistent = sal_True;
|
|
eIOMode = STREAM_IO_DONTKNOW;
|
|
|
|
bIsEof = sal_False;
|
|
}
|
|
|
|
void SvStream::ResetError()
|
|
{
|
|
ClearError();
|
|
}
|
|
|
|
sal_Bool SvStream::ReadByteStringLine( rtl::OUString& rStr, rtl_TextEncoding eSrcCharSet,
|
|
sal_Int32 nMaxBytesToRead )
|
|
{
|
|
rtl::OString aStr;
|
|
sal_Bool bRet = ReadLine( aStr, nMaxBytesToRead);
|
|
rStr = rtl::OStringToOUString(aStr, eSrcCharSet);
|
|
return bRet;
|
|
}
|
|
|
|
sal_Bool SvStream::ReadByteStringLine( String& rStr, rtl_TextEncoding eSrcCharSet )
|
|
{
|
|
rtl::OString aStr;
|
|
sal_Bool bRet = ReadLine(aStr);
|
|
rStr = rtl::OStringToOUString(aStr, eSrcCharSet);
|
|
return bRet;
|
|
}
|
|
|
|
sal_Bool SvStream::ReadLine( rtl::OString& rStr, sal_Int32 nMaxBytesToRead )
|
|
{
|
|
sal_Char buf[256+1];
|
|
sal_Bool bEnd = sal_False;
|
|
sal_Size nOldFilePos = Tell();
|
|
sal_Char c = 0;
|
|
sal_Size nTotalLen = 0;
|
|
|
|
rtl::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.getLength() == 0 )
|
|
{
|
|
// Exit on first block-read error
|
|
bIsEof = sal_True;
|
|
rStr = rtl::OString();
|
|
return sal_False;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
sal_uInt16 j, n;
|
|
for( j = n = 0; j < nLen ; ++j )
|
|
{
|
|
c = buf[j];
|
|
if ( c == '\n' || c == '\r' )
|
|
{
|
|
bEnd = sal_True;
|
|
break;
|
|
}
|
|
if ( n < j )
|
|
buf[n] = c;
|
|
++n;
|
|
}
|
|
nTotalLen += j;
|
|
if (nTotalLen > static_cast<sal_Size>(nMaxBytesToRead))
|
|
{
|
|
n -= nTotalLen - nMaxBytesToRead;
|
|
nTotalLen = nMaxBytesToRead;
|
|
bEnd = sal_True;
|
|
}
|
|
if ( n )
|
|
aBuf.append(buf, n);
|
|
}
|
|
|
|
if ( !bEnd && !GetError() && aBuf.getLength() )
|
|
bEnd = sal_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 = sal_False;
|
|
rStr = aBuf.makeStringAndClear();
|
|
return bEnd;
|
|
}
|
|
|
|
sal_Bool SvStream::ReadUniStringLine( rtl::OUString& rStr, sal_Int32 nMaxCodepointsToRead )
|
|
{
|
|
sal_Unicode buf[256+1];
|
|
sal_Bool bEnd = sal_False;
|
|
sal_Size 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" );
|
|
|
|
rtl::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.getLength() == 0 )
|
|
{
|
|
// exit on first BlockRead error
|
|
bIsEof = sal_True;
|
|
rStr = rtl::OUString();
|
|
return sal_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 = sal_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<sal_Size>(nMaxCodepointsToRead))
|
|
{
|
|
n -= nTotalLen - nMaxCodepointsToRead;
|
|
nTotalLen = nMaxCodepointsToRead;
|
|
bEnd = sal_True;
|
|
}
|
|
if ( n )
|
|
aBuf.append( buf, n );
|
|
}
|
|
|
|
if ( !bEnd && !GetError() && aBuf.getLength() )
|
|
bEnd = sal_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 = sal_False;
|
|
rStr = aBuf.makeStringAndClear();
|
|
return bEnd;
|
|
}
|
|
|
|
sal_Bool SvStream::ReadUniOrByteStringLine( rtl::OUString& rStr, rtl_TextEncoding eSrcCharSet,
|
|
sal_Int32 nMaxCodepointsToRead )
|
|
{
|
|
if ( eSrcCharSet == RTL_TEXTENCODING_UNICODE )
|
|
return ReadUniStringLine( rStr, nMaxCodepointsToRead );
|
|
else
|
|
return ReadByteStringLine( rStr, eSrcCharSet, nMaxCodepointsToRead );
|
|
}
|
|
|
|
rtl::OString read_zeroTerminated_uInt8s_ToOString(SvStream& rStream)
|
|
{
|
|
rtl::OStringBuffer aOutput(256);
|
|
|
|
sal_Char buf[ 256 + 1 ];
|
|
sal_Bool bEnd = sal_False;
|
|
sal_Size 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();
|
|
}
|
|
|
|
rtl::OUString read_zeroTerminated_uInt8s_ToOUString(SvStream& rStream, rtl_TextEncoding eEnc)
|
|
{
|
|
return rtl::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 rtl::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;
|
|
}
|
|
|
|
sal_Bool SvStream::WriteUnicodeOrByteText( const String& rStr, rtl_TextEncoding eDestCharSet )
|
|
{
|
|
if ( eDestCharSet == RTL_TEXTENCODING_UNICODE )
|
|
{
|
|
write_uInt16s_FromOUString(*this, rStr, rStr.Len());
|
|
return nError == SVSTREAM_OK;
|
|
}
|
|
else
|
|
{
|
|
rtl::OString aStr(rtl::OUStringToOString(rStr, eDestCharSet));
|
|
write_uInt8s_FromOString(*this, aStr, aStr.getLength());
|
|
return nError == SVSTREAM_OK;
|
|
}
|
|
}
|
|
|
|
sal_Bool SvStream::WriteByteStringLine( const String& rStr, rtl_TextEncoding eDestCharSet )
|
|
{
|
|
return WriteLine(rtl::OUStringToOString(rStr, eDestCharSet));
|
|
}
|
|
|
|
sal_Bool SvStream::WriteLine(const rtl::OString& rStr)
|
|
{
|
|
Write(rStr.getStr(), rStr.getLength());
|
|
endl(*this);
|
|
return nError == SVSTREAM_OK;
|
|
}
|
|
|
|
sal_Bool SvStream::WriteUniOrByteChar( sal_Unicode ch, rtl_TextEncoding eDestCharSet )
|
|
{
|
|
if ( eDestCharSet == RTL_TEXTENCODING_UNICODE )
|
|
*this << ch;
|
|
else
|
|
{
|
|
rtl::OString aStr(&ch, 1, eDestCharSet);
|
|
Write(aStr.getStr(), aStr.getLength());
|
|
}
|
|
return nError == SVSTREAM_OK;
|
|
}
|
|
|
|
sal_Bool SvStream::StartWritingUnicodeText()
|
|
{
|
|
SetEndianSwap( sal_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
|
|
*this << sal_uInt16( 0xfeff );
|
|
return nError == SVSTREAM_OK;
|
|
}
|
|
|
|
sal_Bool SvStream::StartReadingUnicodeText( rtl_TextEncoding eReadBomCharSet )
|
|
{
|
|
if (!( eReadBomCharSet == RTL_TEXTENCODING_DONTKNOW ||
|
|
eReadBomCharSet == RTL_TEXTENCODING_UNICODE ||
|
|
eReadBomCharSet == RTL_TEXTENCODING_UTF8))
|
|
return sal_True; // nothing to read
|
|
|
|
bool bTryUtf8 = false;
|
|
sal_uInt16 nFlag;
|
|
sal_sSize nBack = sizeof(nFlag);
|
|
*this >> 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)
|
|
{
|
|
sal_uChar nChar;
|
|
nBack += sizeof(nChar);
|
|
*this >> nChar;
|
|
if (nChar == 0xbf)
|
|
nBack = 0; // it is UTF-8
|
|
}
|
|
if (nBack)
|
|
SeekRel( -nBack ); // no BOM, pure data
|
|
return nError == SVSTREAM_OK;
|
|
}
|
|
|
|
sal_Size SvStream::SeekRel( sal_sSize nPos )
|
|
{
|
|
sal_Size nActualPos = Tell();
|
|
|
|
if ( nPos >= 0 )
|
|
{
|
|
if ( SAL_MAX_SIZE - nActualPos > (sal_Size)nPos )
|
|
nActualPos += nPos;
|
|
}
|
|
else
|
|
{
|
|
sal_Size nAbsPos = (sal_Size)-nPos;
|
|
if ( nActualPos >= nAbsPos )
|
|
nActualPos -= nAbsPos;
|
|
}
|
|
|
|
pBufPos = pRWBuf + nActualPos;
|
|
return Seek( nActualPos );
|
|
}
|
|
|
|
SvStream& SvStream::operator>>(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::operator>>(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::operator>>(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::operator>>(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::operator>>(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::operator>>(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::operator>>( signed char& r )
|
|
{
|
|
if( (eIOMode == STREAM_IO_READ || !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::operator>>( char& r )
|
|
{
|
|
if( (eIOMode == STREAM_IO_READ || !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::operator>>( unsigned char& r )
|
|
{
|
|
if( (eIOMode == STREAM_IO_READ || !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::operator>>(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::operator>>(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::operator>> ( 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::operator<< ( sal_uInt16 v )
|
|
{
|
|
if( bSwap )
|
|
SwapUShort(v);
|
|
WRITENUMBER_WITHOUT_SWAP(sal_uInt16,v)
|
|
return *this;
|
|
}
|
|
|
|
SvStream& SvStream::operator<< ( sal_uInt32 v )
|
|
{
|
|
if( bSwap )
|
|
SwapULong(v);
|
|
WRITENUMBER_WITHOUT_SWAP(sal_uInt32,v)
|
|
return *this;
|
|
}
|
|
|
|
SvStream& SvStream::operator<< ( sal_uInt64 v )
|
|
{
|
|
if( bSwap )
|
|
SwapUInt64(v);
|
|
WRITENUMBER_WITHOUT_SWAP(sal_uInt64,v)
|
|
return *this;
|
|
}
|
|
|
|
SvStream& SvStream::operator<< ( sal_Int16 v )
|
|
{
|
|
if( bSwap )
|
|
SwapShort(v);
|
|
WRITENUMBER_WITHOUT_SWAP(sal_Int16,v)
|
|
return *this;
|
|
}
|
|
|
|
SvStream& SvStream::operator<< ( sal_Int32 v )
|
|
{
|
|
if( bSwap )
|
|
SwapLongInt(v);
|
|
WRITENUMBER_WITHOUT_SWAP(sal_Int32,v)
|
|
return *this;
|
|
}
|
|
|
|
SvStream& SvStream::operator<< ( sal_Int64 v )
|
|
{
|
|
if( bSwap )
|
|
SwapInt64(v);
|
|
WRITENUMBER_WITHOUT_SWAP(sal_Int64,v)
|
|
return *this;
|
|
}
|
|
|
|
SvStream& SvStream::operator<< ( signed char v )
|
|
{
|
|
//SDO
|
|
int tmp = eIOMode;
|
|
if(tmp == STREAM_IO_WRITE && sizeof(signed char) <= nBufFree )
|
|
{
|
|
*pBufPos = v;
|
|
pBufPos++; // sizeof(char);
|
|
nBufActualPos++;
|
|
if( nBufActualPos > nBufActualLen ) // Append ?
|
|
nBufActualLen = nBufActualPos;
|
|
nBufFree--; // = sizeof(char);
|
|
bIsDirty = sal_True;
|
|
}
|
|
else
|
|
Write( (char*)&v, sizeof(signed char) );
|
|
return *this;
|
|
}
|
|
|
|
// Special treatment for Chars due to PutBack
|
|
|
|
SvStream& SvStream::operator<< ( char v )
|
|
{
|
|
//SDO
|
|
int tmp = eIOMode;
|
|
if(tmp == STREAM_IO_WRITE && sizeof(char) <= nBufFree )
|
|
{
|
|
*pBufPos = v;
|
|
pBufPos++; // sizeof(char);
|
|
nBufActualPos++;
|
|
if( nBufActualPos > nBufActualLen ) // Append ?
|
|
nBufActualLen = nBufActualPos;
|
|
nBufFree--; // = sizeof(char);
|
|
bIsDirty = sal_True;
|
|
}
|
|
else
|
|
Write( (char*)&v, sizeof(char) );
|
|
return *this;
|
|
}
|
|
|
|
SvStream& SvStream::operator<< ( unsigned char v )
|
|
{
|
|
//SDO
|
|
int tmp = eIOMode;
|
|
if(tmp == STREAM_IO_WRITE && sizeof(char) <= nBufFree )
|
|
{
|
|
*(unsigned char*)pBufPos = v;
|
|
pBufPos++; // = sizeof(char);
|
|
nBufActualPos++; // = sizeof(char);
|
|
if( nBufActualPos > nBufActualLen ) // Append ?
|
|
nBufActualLen = nBufActualPos;
|
|
nBufFree--;
|
|
bIsDirty = sal_True;
|
|
}
|
|
else
|
|
Write( (char*)&v, sizeof(char) );
|
|
return *this;
|
|
}
|
|
|
|
SvStream& SvStream::operator<< ( float v )
|
|
{
|
|
#ifdef UNX
|
|
if( bSwap )
|
|
SwapFloat(v);
|
|
#endif
|
|
WRITENUMBER_WITHOUT_SWAP(float,v)
|
|
return *this;
|
|
}
|
|
|
|
SvStream& SvStream::operator<< ( 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::operator<< ( const char* pBuf )
|
|
{
|
|
Write( pBuf, strlen( pBuf ) );
|
|
return *this;
|
|
}
|
|
|
|
SvStream& SvStream::operator<< ( const unsigned char* pBuf )
|
|
{
|
|
Write( (char*)pBuf, strlen( (char*)pBuf ) );
|
|
return *this;
|
|
}
|
|
|
|
SvStream& SvStream::operator<< ( 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;
|
|
}
|
|
|
|
rtl::OUString SvStream::ReadUniOrByteString( rtl_TextEncoding eSrcCharSet )
|
|
{
|
|
// read UTF-16 string directly from stream ?
|
|
if (eSrcCharSet == RTL_TEXTENCODING_UNICODE)
|
|
return read_lenPrefixed_uInt16s_ToOUString<sal_uInt32>(*this);
|
|
return read_lenPrefixed_uInt8s_ToOUString<sal_uInt16>(*this, eSrcCharSet);
|
|
}
|
|
|
|
SvStream& SvStream::WriteUniOrByteString( const rtl::OUString& rStr, rtl_TextEncoding eDestCharSet )
|
|
{
|
|
// write UTF-16 string directly into stream ?
|
|
if (eDestCharSet == RTL_TEXTENCODING_UNICODE)
|
|
write_lenPrefixed_uInt16s_FromOUString<sal_uInt32>(*this, rStr);
|
|
else
|
|
write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(*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);
|
|
nBufFilePos += nCount;
|
|
}
|
|
else
|
|
{
|
|
// check if block is completely within buffer
|
|
eIOMode = STREAM_IO_READ;
|
|
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( nBufFilePos );
|
|
if( nCryptMask )
|
|
CryptAndWriteBuffer(pRWBuf, nBufActualLen);
|
|
else
|
|
PutData( pRWBuf, nBufActualLen );
|
|
bIsDirty = sal_False;
|
|
}
|
|
|
|
// Does data block fit into buffer?
|
|
if( nCount > nBufSize )
|
|
{
|
|
// => No! Thus read directly
|
|
// into target area without using the buffer
|
|
|
|
eIOMode = STREAM_IO_DONTKNOW;
|
|
|
|
SeekPos( nBufFilePos + nBufActualPos );
|
|
nBufActualLen = 0;
|
|
pBufPos = pRWBuf;
|
|
nCount = GetData( (char*)pData, nCount );
|
|
if( nCryptMask )
|
|
EncryptBuffer(pData, nCount);
|
|
nBufFilePos += nCount;
|
|
nBufFilePos += nBufActualPos;
|
|
nBufActualPos = 0;
|
|
}
|
|
else
|
|
{
|
|
// => Yes. Fill buffer first, then copy to target area
|
|
|
|
nBufFilePos += nBufActualPos;
|
|
SeekPos( 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 = sal_False;
|
|
nBufFree = nBufActualLen - nBufActualPos;
|
|
if( nCount != nSaveCount && nError != ERRCODE_IO_PENDING )
|
|
bIsEof = sal_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 );
|
|
nBufFilePos += nCount;
|
|
return nCount;
|
|
}
|
|
|
|
eIOMode = STREAM_IO_WRITE;
|
|
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 = sal_True;
|
|
}
|
|
else
|
|
{
|
|
// Does stream require flushing?
|
|
if( bIsDirty )
|
|
{
|
|
SeekPos( nBufFilePos );
|
|
if( nCryptMask )
|
|
CryptAndWriteBuffer( pRWBuf, (sal_Size)nBufActualLen );
|
|
else
|
|
PutData( pRWBuf, nBufActualLen );
|
|
bIsDirty = sal_False;
|
|
}
|
|
|
|
// Does data block fit into buffer?
|
|
if( nCount > nBufSize )
|
|
{
|
|
eIOMode = STREAM_IO_DONTKNOW;
|
|
nBufFilePos += nBufActualPos;
|
|
nBufActualLen = 0;
|
|
nBufActualPos = 0;
|
|
pBufPos = pRWBuf;
|
|
SeekPos( nBufFilePos );
|
|
if( nCryptMask )
|
|
nCount = CryptAndWriteBuffer( pData, nCount );
|
|
else
|
|
nCount = PutData( (char*)pData, nCount );
|
|
nBufFilePos += nCount;
|
|
}
|
|
else
|
|
{
|
|
// Copy block to buffer
|
|
memcpy( pRWBuf, pData, (size_t)nCount );
|
|
|
|
// Mind the order!
|
|
nBufFilePos += nBufActualPos;
|
|
nBufActualPos = (sal_uInt16)nCount;
|
|
pBufPos = pRWBuf + nCount;
|
|
nBufActualLen = (sal_uInt16)nCount;
|
|
bIsDirty = sal_True;
|
|
}
|
|
}
|
|
nBufFree = nBufSize - nBufActualPos;
|
|
return nCount;
|
|
}
|
|
|
|
sal_Size SvStream::Seek( sal_Size nFilePos )
|
|
{
|
|
eIOMode = STREAM_IO_DONTKNOW;
|
|
|
|
bIsEof = sal_False;
|
|
if( !pRWBuf )
|
|
{
|
|
nBufFilePos = SeekPos( nFilePos );
|
|
DBG_ASSERT(Tell()==nBufFilePos,"Out Of Sync!");
|
|
return nBufFilePos;
|
|
}
|
|
|
|
// Is seek position within buffer?
|
|
if( nFilePos >= nBufFilePos && nFilePos <= (nBufFilePos + nBufActualLen))
|
|
{
|
|
nBufActualPos = (sal_uInt16)(nFilePos - nBufFilePos);
|
|
pBufPos = pRWBuf + nBufActualPos;
|
|
// Update nBufFree to avoid crash upon PutBack
|
|
nBufFree = nBufActualLen - nBufActualPos;
|
|
}
|
|
else
|
|
{
|
|
if( bIsDirty && bIsConsistent)
|
|
{
|
|
SeekPos( nBufFilePos );
|
|
if( nCryptMask )
|
|
CryptAndWriteBuffer( pRWBuf, nBufActualLen );
|
|
else
|
|
PutData( pRWBuf, nBufActualLen );
|
|
bIsDirty = sal_False;
|
|
}
|
|
nBufActualLen = 0;
|
|
nBufActualPos = 0;
|
|
pBufPos = pRWBuf;
|
|
nBufFilePos = SeekPos( nFilePos );
|
|
}
|
|
#ifdef OV_DEBUG
|
|
{
|
|
sal_Size nDebugTemp = nBufFilePos + nBufActualPos;
|
|
DBG_ASSERT(Tell()==nDebugTemp,"Sync?");
|
|
}
|
|
#endif
|
|
return 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_Size SvStream::remainingSize()
|
|
{
|
|
sal_Size nCurr = Tell();
|
|
sal_Size nEnd = Seek(STREAM_SEEK_TO_END);
|
|
sal_Size nMaxAvailable = nEnd-nCurr;
|
|
Seek(nCurr);
|
|
return nMaxAvailable;
|
|
}
|
|
|
|
void SvStream::Flush()
|
|
{
|
|
if( bIsDirty && bIsConsistent )
|
|
{
|
|
SeekPos( nBufFilePos );
|
|
if( nCryptMask )
|
|
CryptAndWriteBuffer( pRWBuf, (sal_Size)nBufActualLen );
|
|
else
|
|
if( PutData( pRWBuf, nBufActualLen ) != nBufActualLen )
|
|
SetError( SVSTREAM_WRITE_ERROR );
|
|
bIsDirty = sal_False;
|
|
}
|
|
if( bIsWritable )
|
|
FlushData();
|
|
}
|
|
|
|
void SvStream::RefreshBuffer()
|
|
{
|
|
if( bIsDirty && bIsConsistent )
|
|
{
|
|
SeekPos( nBufFilePos );
|
|
if( nCryptMask )
|
|
CryptAndWriteBuffer( pRWBuf, (sal_Size)nBufActualLen );
|
|
else
|
|
PutData( pRWBuf, nBufActualLen );
|
|
bIsDirty = sal_False;
|
|
}
|
|
SeekPos( nBufFilePos );
|
|
nBufActualLen = (sal_uInt16)GetData( pRWBuf, nBufSize );
|
|
if( nBufActualLen && nError == ERRCODE_IO_PENDING )
|
|
nError = ERRCODE_NONE;
|
|
if( nCryptMask )
|
|
EncryptBuffer(pRWBuf, (sal_Size)nBufActualLen);
|
|
bIsConsistent = sal_True;
|
|
eIOMode = STREAM_IO_DONTKNOW;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
sal_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 sal_True;
|
|
}
|
|
|
|
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 rtl::OString& rCryptMaskKey)
|
|
{
|
|
m_aCryptMaskKey = rCryptMaskKey;
|
|
nCryptMask = implGetCryptMask(m_aCryptMaskKey.getStr(),
|
|
m_aCryptMaskKey.getLength(), GetVersion());
|
|
}
|
|
|
|
void SvStream::SyncSvStream( sal_Size nNewStreamPos )
|
|
{
|
|
ClearBuffer();
|
|
SvStream::nBufFilePos = nNewStreamPos;
|
|
}
|
|
|
|
void SvStream::SyncSysStream()
|
|
{
|
|
Flush();
|
|
SeekPos( Tell() );
|
|
}
|
|
|
|
sal_Bool SvStream::SetStreamSize( sal_Size nSize )
|
|
{
|
|
#ifdef DBG_UTIL
|
|
sal_Size nFPos = Tell();
|
|
#endif
|
|
sal_uInt16 nBuf = nBufSize;
|
|
SetBufferSize( 0 );
|
|
SetSize( nSize );
|
|
SetBufferSize( nBuf );
|
|
DBG_ASSERT(Tell()==nFPos,"SetStreamSize failed");
|
|
return (sal_Bool)(nError == 0);
|
|
}
|
|
|
|
SvStream& endl( SvStream& rStr )
|
|
{
|
|
LineEnd eDelim = rStr.GetLineDelimiter();
|
|
if ( eDelim == LINEEND_CR )
|
|
rStr << _CR;
|
|
else if( eDelim == LINEEND_LF )
|
|
rStr << _LF;
|
|
else
|
|
rStr << _CR << _LF;
|
|
return rStr;
|
|
}
|
|
|
|
SvStream& endlu( SvStream& rStrm )
|
|
{
|
|
switch ( rStrm.GetLineDelimiter() )
|
|
{
|
|
case LINEEND_CR :
|
|
rStrm << sal_Unicode(_CR);
|
|
break;
|
|
case LINEEND_LF :
|
|
rStrm << sal_Unicode(_LF);
|
|
break;
|
|
default:
|
|
rStrm << sal_Unicode(_CR) << sal_Unicode(_LF);
|
|
}
|
|
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 = sal_True;
|
|
else
|
|
bIsWritable = sal_False;
|
|
nEndOfData = bufSize;
|
|
bOwnsData = sal_False;
|
|
pBuf = (sal_uInt8 *) pBuffer;
|
|
nResize = 0L;
|
|
nSize = bufSize;
|
|
nPos = 0L;
|
|
SetBufferSize( 0 );
|
|
}
|
|
|
|
SvMemoryStream::SvMemoryStream( sal_Size nInitSize, sal_Size nResizeOffset )
|
|
{
|
|
bIsWritable = sal_True;
|
|
bOwnsData = sal_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();
|
|
}
|
|
}
|
|
|
|
sal_uInt16 SvMemoryStream::IsA() const
|
|
{
|
|
return (sal_uInt16)ID_MEMORYSTREAM;
|
|
}
|
|
|
|
void* SvMemoryStream::SetBuffer( void* pNewBuf, sal_Size nCount,
|
|
sal_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();
|
|
|
|
DBG_ASSERT( nEndOfData<STREAM_SEEK_TO_END,"Invalid EOF");
|
|
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_Size SvMemoryStream::SeekPos( sal_Size nNewPos )
|
|
{
|
|
// nEndOfData: First position in stream not allowed to read from
|
|
// nSize: Size of allocated buffer
|
|
|
|
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();
|
|
}
|
|
|
|
sal_Bool SvMemoryStream::AllocateMemory( sal_Size nNewSize )
|
|
{
|
|
pBuf = new sal_uInt8[nNewSize];
|
|
return( pBuf != 0 );
|
|
}
|
|
|
|
// (using Bozo algorithm)
|
|
sal_Bool SvMemoryStream::ReAllocateMemory( long nDiff )
|
|
{
|
|
sal_Bool bRetVal = sal_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 = sal_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 = sal_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_Size nNewSize )
|
|
{
|
|
long nDiff = (long)nNewSize - (long)nSize;
|
|
ReAllocateMemory( nDiff );
|
|
}
|
|
|
|
TYPEINIT0 ( SvDataCopyStream )
|
|
|
|
void SvDataCopyStream::Assign( const SvDataCopyStream& )
|
|
{
|
|
}
|
|
|
|
//Create a OString of nLen bytes from rStream
|
|
rtl::OString read_uInt8s_ToOString(SvStream& rStrm, sal_Size nLen)
|
|
{
|
|
using comphelper::string::rtl_string_alloc;
|
|
|
|
rtl_String *pStr = NULL;
|
|
if (nLen)
|
|
{
|
|
nLen = std::min(nLen, static_cast<sal_Size>(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<sal_Int32>(nLen));
|
|
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<sal_Int32>(nWasRead);
|
|
pStr->buffer[pStr->length] = 0;
|
|
}
|
|
}
|
|
|
|
//take ownership of buffer and return, otherwise return empty string
|
|
return pStr ? rtl::OString(pStr, SAL_NO_ACQUIRE) : rtl::OString();
|
|
}
|
|
|
|
//Create a OUString of nLen sal_Unicodes from rStream
|
|
rtl::OUString read_uInt16s_ToOUString(SvStream& rStrm, sal_Size nLen)
|
|
{
|
|
using comphelper::string::rtl_uString_alloc;
|
|
|
|
rtl_uString *pStr = NULL;
|
|
if (nLen)
|
|
{
|
|
nLen = std::min(nLen, static_cast<sal_Size>(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<sal_Int32>(nLen));
|
|
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<sal_Int32>(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 ? rtl::OUString(pStr, SAL_NO_ACQUIRE) : rtl::OUString();
|
|
}
|
|
|
|
namespace
|
|
{
|
|
template <typename T, typename O> 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] == _CR) || (rIn[i] == _LF) )
|
|
{
|
|
nLen = nLen + nLineEndLen;
|
|
|
|
// If set already, skip expensive test
|
|
if ( !bConvert )
|
|
{
|
|
// Muessen wir Konvertieren
|
|
if ( ((eLineEnd != LINEEND_LF) && (rIn[i] == _LF)) ||
|
|
((eLineEnd == LINEEND_CRLF) && (rIn[i+1] != _LF)) ||
|
|
((eLineEnd == LINEEND_LF) &&
|
|
((rIn[i] == _CR) || (rIn[i+1] == _CR))) ||
|
|
((eLineEnd == LINEEND_CR) &&
|
|
((rIn[i] == _LF) || (rIn[i+1] == _LF))) )
|
|
bConvert = true;
|
|
}
|
|
|
|
// skip char if \r\n oder \n\r
|
|
if ( ((rIn[i+1] == _CR) || (rIn[i+1] == _LF)) &&
|
|
(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] == _CR) || (rIn[i] == _LF) )
|
|
{
|
|
if ( eLineEnd == LINEEND_CRLF )
|
|
{
|
|
aNewData.append(_CR);
|
|
aNewData.append(_LF);
|
|
}
|
|
else
|
|
{
|
|
if ( eLineEnd == LINEEND_CR )
|
|
aNewData.append(_CR);
|
|
else
|
|
aNewData.append(_LF);
|
|
}
|
|
|
|
if ( ((rIn[i+1] == _CR) || (rIn[i+1] == _LF)) &&
|
|
(rIn[i] != rIn[i+1]) )
|
|
++i;
|
|
}
|
|
else
|
|
{
|
|
aNewData.append(rIn[i]);
|
|
}
|
|
|
|
++i;
|
|
}
|
|
|
|
return aNewData.makeStringAndClear();
|
|
}
|
|
}
|
|
|
|
rtl::OString convertLineEnd(const rtl::OString &rIn, LineEnd eLineEnd)
|
|
{
|
|
return tmpl_convertLineEnd<rtl::OString, rtl::OStringBuffer>(rIn, eLineEnd);
|
|
}
|
|
|
|
rtl::OUString convertLineEnd(const rtl::OUString &rIn, LineEnd eLineEnd)
|
|
{
|
|
return tmpl_convertLineEnd<rtl::OUString, rtl::OUStringBuffer>(rIn, eLineEnd);
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|