1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 // TODO: Read->RefreshBuffer-> React to changes from m_nBufActualLen
29 #include <osl/endian.h>
30 #include <osl/diagnose.h>
31 #include <sal/log.hxx>
33 #include <comphelper/fileformat.h>
34 #include <comphelper/string.hxx>
36 #define SWAPNIBBLES(c) \
37 unsigned char nSwapTmp=c; \
42 #include <tools/debug.hxx>
43 #include <tools/stream.hxx>
44 #include <osl/thread.h>
47 // !!! Do not inline if already the operators <<,>> are inline
48 inline static void SwapUShort( sal_uInt16
& r
)
49 { r
= OSL_SWAPWORD(r
); }
50 inline static void SwapShort( short& r
)
51 { r
= OSL_SWAPWORD(r
); }
52 inline static void SwapULong( sal_uInt32
& r
)
53 { r
= OSL_SWAPDWORD(r
); }
54 inline static void SwapLongInt( sal_Int32
& r
)
55 { r
= OSL_SWAPDWORD(r
); }
57 inline static void SwapUInt64( sal_uInt64
& r
)
66 s
.c
[0] ^= s
.c
[1]; // swap the 32 bit words
69 // swap the bytes in the words
70 s
.c
[0] = OSL_SWAPDWORD(s
.c
[0]);
71 s
.c
[1] = OSL_SWAPDWORD(s
.c
[1]);
74 inline static void SwapInt64( sal_Int64
& r
)
83 s
.c
[0] ^= s
.c
[1]; // swap the 32 bit words
86 // swap the bytes in the words
87 s
.c
[0] = OSL_SWAPDWORD(s
.c
[0]);
88 s
.c
[1] = OSL_SWAPDWORD(s
.c
[1]);
93 inline static void SwapFloat( float& r
)
102 s
.c
= OSL_SWAPDWORD( s
.c
);
106 inline static void SwapDouble( double& r
)
108 if( sizeof(double) != 8 )
110 SAL_WARN( "tools.stream", "Can only swap 8-Byte-doubles" );
121 s
.c
[0] ^= s
.c
[1]; // swap 32-bit values in situ
124 s
.c
[0] = OSL_SWAPDWORD(s
.c
[0]); // swap dword itself in situ
125 s
.c
[1] = OSL_SWAPDWORD(s
.c
[1]);
131 static void SwapUnicode(sal_Unicode
& r
) { r
= OSL_SWAPWORD(r
); }
135 void SvStream::readNumberWithoutSwap_(void * pDataDest
, int nDataSize
)
137 if (m_isIoRead
&& nDataSize
<= m_nBufFree
)
139 for (int i
= 0; i
< nDataSize
; i
++)
140 static_cast<char*>(pDataDest
)[i
] = m_pBufPos
[i
];
141 m_nBufActualPos
+= nDataSize
;
142 m_pBufPos
+= nDataSize
;
143 m_nBufFree
-= nDataSize
;
147 ReadBytes( pDataDest
, nDataSize
);
152 void SvStream::writeNumberWithoutSwap_(const void * pDataSrc
, int nDataSize
)
154 if (m_isIoWrite
&& nDataSize
<= m_nBufFree
)
156 for (int i
= 0; i
< nDataSize
; i
++)
157 m_pBufPos
[i
] = static_cast<const char*>(pDataSrc
)[i
];
158 m_nBufFree
-= nDataSize
;
159 m_nBufActualPos
+= nDataSize
;
160 if (m_nBufActualPos
> m_nBufActualLen
)
161 m_nBufActualLen
= m_nBufActualPos
;
162 m_pBufPos
+= nDataSize
;
167 WriteBytes( pDataSrc
, nDataSize
);
173 void SvLockBytes::close()
182 ErrCode
SvLockBytes::ReadAt(sal_uInt64
const nPos
, void * pBuffer
, std::size_t nCount
,
183 std::size_t * pRead
) const
187 OSL_FAIL("SvLockBytes::ReadAt(): Bad stream");
191 m_pStream
->Seek(nPos
);
192 std::size_t nTheRead
= m_pStream
->ReadBytes(pBuffer
, nCount
);
195 return m_pStream
->GetErrorCode();
199 ErrCode
SvLockBytes::WriteAt(sal_uInt64
const nPos
, const void * pBuffer
, std::size_t nCount
,
200 std::size_t * pWritten
)
204 OSL_FAIL("SvLockBytes::WriteAt(): Bad stream");
208 m_pStream
->Seek(nPos
);
209 std::size_t nTheWritten
= m_pStream
->WriteBytes(pBuffer
, nCount
);
211 *pWritten
= nTheWritten
;
212 return m_pStream
->GetErrorCode();
216 ErrCode
SvLockBytes::Flush() const
220 OSL_FAIL("SvLockBytes::Flush(): Bad stream");
225 return m_pStream
->GetErrorCode();
229 ErrCode
SvLockBytes::SetSize(sal_uInt64
const nSize
)
233 OSL_FAIL("SvLockBytes::SetSize(): Bad stream");
237 m_pStream
->SetStreamSize(nSize
);
238 return m_pStream
->GetErrorCode();
241 ErrCode
SvLockBytes::Stat(SvLockBytesStat
* pStat
, SvLockBytesStatFlag
) const
245 OSL_FAIL("SvLockBytes::Stat(): Bad stream");
251 sal_uInt64
const nPos
= m_pStream
->Tell();
252 pStat
->nSize
= m_pStream
->Seek(STREAM_SEEK_TO_END
);
253 m_pStream
->Seek(nPos
);
260 std::size_t SvStream::GetData( void* pData
, std::size_t nSize
)
264 DBG_ASSERT( m_xLockBytes
.is(), "pure virtual function" );
266 m_nError
= m_xLockBytes
->ReadAt(m_nActPos
, pData
, nSize
, &nRet
);
273 std::size_t SvStream::PutData( const void* pData
, std::size_t nSize
)
277 DBG_ASSERT( m_xLockBytes
.is(), "pure virtual function" );
279 m_nError
= m_xLockBytes
->WriteAt(m_nActPos
, pData
, nSize
, &nRet
);
286 sal_uInt64
SvStream::SeekPos(sal_uInt64
const nPos
)
288 // check if a truncated STREAM_SEEK_TO_END was passed
289 assert(nPos
!= SAL_MAX_UINT32
);
290 if( !GetError() && nPos
== STREAM_SEEK_TO_END
)
292 DBG_ASSERT( m_xLockBytes
.is(), "pure virtual function" );
293 SvLockBytesStat aStat
;
294 m_xLockBytes
->Stat( &aStat
, SVSTATFLAG_DEFAULT
);
295 m_nActPos
= aStat
.nSize
;
302 void SvStream::FlushData()
306 DBG_ASSERT( m_xLockBytes
.is(), "pure virtual function" );
307 m_nError
= m_xLockBytes
->Flush();
311 void SvStream::SetSize(sal_uInt64
const nSize
)
313 DBG_ASSERT( m_xLockBytes
.is(), "pure virtual function" );
314 m_nError
= m_xLockBytes
->SetSize( nSize
);
317 SvStream::SvStream() :
330 , m_isConsistent(true)
333 , m_nCompressMode(SvStreamCompressFlags::NONE
)
335 , m_eLineDelimiter(LINEEND_LF
) // UNIX-Format
337 , m_eLineDelimiter(LINEEND_CRLF
) // DOS-Format
339 , m_eStreamCharSet(osl_getThreadTextEncoding())
346 , m_eStreamMode(StreamMode::NONE
)
350 SetEndian( SvStreamEndian::LITTLE
);
355 SvStream::SvStream( SvLockBytes
* pLockBytesP
) : SvStream()
357 m_xLockBytes
= pLockBytesP
;
359 const SvStream
* pStrm
= pLockBytesP
->GetStream();
361 SetError( pStrm
->GetErrorCode() );
364 SetBufferSize( 256 );
367 SvStream::~SvStream()
369 if (m_xLockBytes
.is())
373 void SvStream::ClearError()
376 m_nError
= ERRCODE_NONE
;
379 void SvStream::SetError( ErrCode nErrorCode
)
381 if (m_nError
== ERRCODE_NONE
)
382 m_nError
= nErrorCode
;
385 void SvStream::SetEndian( SvStreamEndian nNewFormat
)
387 m_nEndian
= nNewFormat
;
390 if (m_nEndian
== SvStreamEndian::LITTLE
)
393 if (m_nEndian
== SvStreamEndian::BIG
)
398 void SvStream::SetBufferSize( sal_uInt16 nBufferSize
)
400 sal_uInt64
const nActualFilePos
= Tell();
401 bool bDontSeek
= (m_pRWBuf
== nullptr);
403 if (m_isDirty
&& m_isConsistent
&& m_isWritable
) // due to Windows NT: Access denied
409 m_nBufFilePos
+= m_nBufActualPos
;
415 m_nBufSize
= nBufferSize
;
417 m_pRWBuf
.reset(new sal_uInt8
[ m_nBufSize
]);
418 m_isConsistent
= true;
419 m_pBufPos
= m_pRWBuf
.get();
420 m_isIoRead
= m_isIoWrite
= false;
422 SeekPos( nActualFilePos
);
425 void SvStream::ClearBuffer()
430 m_pBufPos
= m_pRWBuf
.get();
432 m_isConsistent
= true;
433 m_isIoRead
= m_isIoWrite
= false;
438 void SvStream::ResetError()
443 bool SvStream::ReadByteStringLine( OUString
& rStr
, rtl_TextEncoding eSrcCharSet
,
444 sal_Int32 nMaxBytesToRead
)
447 bool bRet
= ReadLine( aStr
, nMaxBytesToRead
);
448 rStr
= OStringToOUString(aStr
, eSrcCharSet
);
452 bool SvStream::ReadLine( OString
& rStr
, sal_Int32 nMaxBytesToRead
)
456 sal_uInt64 nOldFilePos
= Tell();
458 std::size_t nTotalLen
= 0;
460 OStringBuffer
aBuf(4096);
461 while( !bEnd
&& !GetError() ) // Don't test for EOF as we
462 // are reading block-wise!
464 sal_uInt16 nLen
= static_cast<sal_uInt16
>(ReadBytes(buf
, sizeof(buf
)-1));
467 if ( aBuf
.isEmpty() )
469 // Exit on first block-read error
479 for( j
= n
= 0; j
< nLen
; ++j
)
482 if ( c
== '\n' || c
== '\r' )
492 if (nTotalLen
> static_cast<std::size_t>(nMaxBytesToRead
))
494 n
-= nTotalLen
- nMaxBytesToRead
;
495 nTotalLen
= nMaxBytesToRead
;
502 if ( !bEnd
&& !GetError() && !aBuf
.isEmpty() )
505 nOldFilePos
+= nTotalLen
;
506 if( Tell() > nOldFilePos
)
508 Seek( nOldFilePos
); // Seek pointer due to BlockRead above
510 if ( bEnd
&& (c
=='\r' || c
=='\n') ) // Special treatment for DOS files
513 std::size_t nLen
= ReadBytes(&cTemp
, sizeof(cTemp
));
515 if( cTemp
== c
|| (cTemp
!= '\n' && cTemp
!= '\r') )
522 rStr
= aBuf
.makeStringAndClear();
526 bool SvStream::ReadUniStringLine( OUString
& rStr
, sal_Int32 nMaxCodepointsToRead
)
528 sal_Unicode buf
[256+1];
530 sal_uInt64 nOldFilePos
= Tell();
532 std::size_t nTotalLen
= 0;
534 DBG_ASSERT( sizeof(sal_Unicode
) == sizeof(sal_uInt16
), "ReadUniStringLine: swapping sizeof(sal_Unicode) not implemented" );
536 OUStringBuffer
aBuf(4096);
537 while( !bEnd
&& !GetError() ) // Don't test for EOF as we
538 // are reading block-wise!
540 sal_uInt16 nLen
= static_cast<sal_uInt16
>(ReadBytes( buf
, sizeof(buf
)-sizeof(sal_Unicode
)));
541 nLen
/= sizeof(sal_Unicode
);
544 if ( aBuf
.isEmpty() )
546 // exit on first BlockRead error
556 for( j
= n
= 0; j
< nLen
; ++j
)
559 SwapUnicode( buf
[n
] );
561 if ( c
== '\n' || c
== '\r' )
566 // erAck 26.02.01: Old behavior was no special treatment of '\0'
567 // character here, but a following rStr+=c did ignore it. Is this
568 // really intended? Or should a '\0' better terminate a line?
569 // The nOldFilePos stuff wasn't correct then anyways.
578 if (nTotalLen
> static_cast<std::size_t>(nMaxCodepointsToRead
))
580 n
-= nTotalLen
- nMaxCodepointsToRead
;
581 nTotalLen
= nMaxCodepointsToRead
;
585 aBuf
.append( buf
, n
);
588 if ( !bEnd
&& !GetError() && !aBuf
.isEmpty() )
591 nOldFilePos
+= nTotalLen
* sizeof(sal_Unicode
);
592 if( Tell() > nOldFilePos
)
593 nOldFilePos
+= sizeof(sal_Unicode
);
594 Seek( nOldFilePos
); // seek due to BlockRead above
596 if ( bEnd
&& (c
=='\r' || c
=='\n') ) // special treatment for DOS files
599 ReadBytes( &cTemp
, sizeof(cTemp
) );
601 SwapUnicode( cTemp
);
602 if( cTemp
== c
|| (cTemp
!= '\n' && cTemp
!= '\r') )
608 rStr
= aBuf
.makeStringAndClear();
612 bool SvStream::ReadUniOrByteStringLine( OUString
& rStr
, rtl_TextEncoding eSrcCharSet
,
613 sal_Int32 nMaxCodepointsToRead
)
615 if ( eSrcCharSet
== RTL_TEXTENCODING_UNICODE
)
616 return ReadUniStringLine( rStr
, nMaxCodepointsToRead
);
618 return ReadByteStringLine( rStr
, eSrcCharSet
, nMaxCodepointsToRead
);
621 OString
read_zeroTerminated_uInt8s_ToOString(SvStream
& rStream
)
623 OStringBuffer
aOutput(256);
625 sal_Char buf
[ 256 + 1 ];
627 sal_uInt64 nFilePos
= rStream
.Tell();
629 while( !bEnd
&& !rStream
.GetError() )
631 std::size_t nLen
= rStream
.ReadBytes(buf
, sizeof(buf
)-1);
635 std::size_t nReallyRead
= nLen
;
636 const sal_Char
* pPtr
= buf
;
637 while (nLen
&& *pPtr
)
643 bEnd
= ( nReallyRead
< sizeof(buf
)-1 ) // read less than attempted to read
644 || ( ( nLen
> 0 ) // OR it is inside the block we read
645 && ( 0 == *pPtr
) // AND found a string terminator
648 aOutput
.append(buf
, pPtr
- buf
);
651 nFilePos
+= aOutput
.getLength();
652 if (rStream
.Tell() > nFilePos
)
653 rStream
.Seek(nFilePos
+1); // seek due to FileRead above
654 return aOutput
.makeStringAndClear();
657 OUString
read_zeroTerminated_uInt8s_ToOUString(SvStream
& rStream
, rtl_TextEncoding eEnc
)
659 return OStringToOUString(
660 read_zeroTerminated_uInt8s_ToOString(rStream
), eEnc
);
663 /** Attempt to write a prefixed sequence of nUnits 16bit units from an OUString,
664 returned value is number of bytes written */
665 std::size_t write_uInt16s_FromOUString(SvStream
& rStrm
, const OUString
& rStr
,
668 DBG_ASSERT( sizeof(sal_Unicode
) == sizeof(sal_uInt16
), "write_uInt16s_FromOUString: swapping sizeof(sal_Unicode) not implemented" );
669 std::size_t nWritten
;
670 if (!rStrm
.IsEndianSwap())
671 nWritten
= rStrm
.WriteBytes(rStr
.getStr(), nUnits
* sizeof(sal_Unicode
));
674 std::size_t nLen
= nUnits
;
675 sal_Unicode aBuf
[384];
676 sal_Unicode
* const pTmp
= ( nLen
> 384 ? new sal_Unicode
[nLen
] : aBuf
);
677 memcpy( pTmp
, rStr
.getStr(), nLen
* sizeof(sal_Unicode
) );
678 sal_Unicode
* p
= pTmp
;
679 const sal_Unicode
* const pStop
= pTmp
+ nLen
;
685 nWritten
= rStrm
.WriteBytes( pTmp
, nLen
* sizeof(sal_Unicode
) );
692 bool SvStream::WriteUnicodeOrByteText( const OUString
& rStr
, rtl_TextEncoding eDestCharSet
)
694 if ( eDestCharSet
== RTL_TEXTENCODING_UNICODE
)
696 write_uInt16s_FromOUString(*this, rStr
, rStr
.getLength());
697 return m_nError
== ERRCODE_NONE
;
701 OString
aStr(OUStringToOString(rStr
, eDestCharSet
));
702 write_uInt8s_FromOString(*this, aStr
, aStr
.getLength());
703 return m_nError
== ERRCODE_NONE
;
707 bool SvStream::WriteByteStringLine( const OUString
& rStr
, rtl_TextEncoding eDestCharSet
)
709 return WriteLine(OUStringToOString(rStr
, eDestCharSet
));
712 bool SvStream::WriteLine(const OString
& rStr
)
714 WriteBytes(rStr
.getStr(), rStr
.getLength());
716 return m_nError
== ERRCODE_NONE
;
719 bool SvStream::WriteUniOrByteChar( sal_Unicode ch
, rtl_TextEncoding eDestCharSet
)
721 if ( eDestCharSet
== RTL_TEXTENCODING_UNICODE
)
725 OString
aStr(&ch
, 1, eDestCharSet
);
726 WriteBytes(aStr
.getStr(), aStr
.getLength());
728 return m_nError
== ERRCODE_NONE
;
731 void SvStream::StartWritingUnicodeText()
733 // BOM, Byte Order Mark, U+FEFF, see
734 // http://www.unicode.org/faq/utf_bom.html#BOM
735 // Upon read: 0xfeff(-257) => no swap; 0xfffe(-2) => swap
736 writeNumberWithoutSwap(sal_uInt16(0xfeff)); // write native format
739 void SvStream::StartReadingUnicodeText( rtl_TextEncoding eReadBomCharSet
)
741 if (!( eReadBomCharSet
== RTL_TEXTENCODING_DONTKNOW
||
742 eReadBomCharSet
== RTL_TEXTENCODING_UNICODE
||
743 eReadBomCharSet
== RTL_TEXTENCODING_UTF8
))
744 return; // nothing to read
746 bool bTryUtf8
= false;
748 sal_sSize nBack
= sizeof(nFlag
);
754 if ( eReadBomCharSet
== RTL_TEXTENCODING_DONTKNOW
||
755 eReadBomCharSet
== RTL_TEXTENCODING_UNICODE
)
760 if ( eReadBomCharSet
== RTL_TEXTENCODING_DONTKNOW
||
761 eReadBomCharSet
== RTL_TEXTENCODING_UNICODE
)
763 SetEndian( m_nEndian
== SvStreamEndian::BIG
? SvStreamEndian::LITTLE
: SvStreamEndian::BIG
);
768 if (m_nEndian
== SvStreamEndian::BIG
&&
769 (eReadBomCharSet
== RTL_TEXTENCODING_DONTKNOW
||
770 eReadBomCharSet
== RTL_TEXTENCODING_UTF8
))
774 if (m_nEndian
== SvStreamEndian::LITTLE
&&
775 (eReadBomCharSet
== RTL_TEXTENCODING_DONTKNOW
||
776 eReadBomCharSet
== RTL_TEXTENCODING_UTF8
))
784 unsigned char nChar(0);
785 nBack
+= sizeof(nChar
);
788 nBack
= 0; // it is UTF-8
791 SeekRel( -nBack
); // no BOM, pure data
794 sal_uInt64
SvStream::SeekRel(sal_Int64
const nPos
)
796 sal_uInt64 nActualPos
= Tell();
800 if (SAL_MAX_UINT64
- nActualPos
> static_cast<sal_uInt64
>(nPos
))
805 sal_uInt64
const nAbsPos
= static_cast<sal_uInt64
>(-nPos
);
806 if ( nActualPos
>= nAbsPos
)
807 nActualPos
-= nAbsPos
;
810 m_pBufPos
= m_pRWBuf
.get() + nActualPos
;
811 return Seek( nActualPos
);
814 SvStream
& SvStream::ReadUInt16(sal_uInt16
& r
)
817 readNumberWithoutSwap(n
);
827 SvStream
& SvStream::ReadUInt32(sal_uInt32
& r
)
830 readNumberWithoutSwap(n
);
840 SvStream
& SvStream::ReadUInt64(sal_uInt64
& r
)
843 readNumberWithoutSwap(n
);
853 SvStream
& SvStream::ReadInt16(sal_Int16
& r
)
856 readNumberWithoutSwap(n
);
866 SvStream
& SvStream::ReadInt32(sal_Int32
& r
)
869 readNumberWithoutSwap(n
);
879 SvStream
& SvStream::ReadInt64(sal_Int64
& r
)
882 readNumberWithoutSwap(n
);
892 SvStream
& SvStream::ReadSChar( signed char& r
)
894 if ((m_isIoRead
|| !m_isConsistent
) &&
895 sizeof(signed char) <= m_nBufFree
)
898 m_nBufActualPos
+= sizeof(signed char);
899 m_pBufPos
+= sizeof(signed char);
900 m_nBufFree
-= sizeof(signed char);
903 ReadBytes( &r
, sizeof(signed char) );
907 // Special treatment for Chars due to PutBack
909 SvStream
& SvStream::ReadChar( char& r
)
911 if ((m_isIoRead
|| !m_isConsistent
) &&
912 sizeof(char) <= m_nBufFree
)
915 m_nBufActualPos
+= sizeof(char);
916 m_pBufPos
+= sizeof(char);
917 m_nBufFree
-= sizeof(char);
920 ReadBytes( &r
, sizeof(char) );
924 SvStream
& SvStream::ReadUChar( unsigned char& r
)
926 if ((m_isIoRead
|| !m_isConsistent
) &&
927 sizeof(char) <= m_nBufFree
)
930 m_nBufActualPos
+= sizeof(char);
931 m_pBufPos
+= sizeof(char);
932 m_nBufFree
-= sizeof(char);
935 ReadBytes( &r
, sizeof(char) );
939 SvStream
& SvStream::ReadUtf16(sal_Unicode
& r
)
942 readNumberWithoutSwap(n
);
952 SvStream
& SvStream::ReadCharAsBool( bool& r
)
954 if ((m_isIoRead
|| !m_isConsistent
) &&
955 sizeof(char) <= m_nBufFree
)
958 *m_pBufPos
> 1, "tools.stream", unsigned(*m_pBufPos
) << " not 0/1");
960 m_nBufActualPos
+= sizeof(char);
961 m_pBufPos
+= sizeof(char);
962 m_nBufFree
-= sizeof(char);
967 if (ReadBytes(&c
, 1) == 1)
969 SAL_WARN_IF(c
> 1, "tools.stream", unsigned(c
) << " not 0/1");
976 SvStream
& SvStream::ReadFloat(float& r
)
979 readNumberWithoutSwap(n
);
991 SvStream
& SvStream::ReadDouble(double& r
)
994 readNumberWithoutSwap(n
);
1006 SvStream
& SvStream::ReadStream( SvStream
& rStream
)
1008 const sal_uInt32 cBufLen
= 0x8000;
1009 std::unique_ptr
<char[]> pBuf( new char[ cBufLen
] );
1013 nCount
= ReadBytes( pBuf
.get(), cBufLen
);
1014 rStream
.WriteBytes( pBuf
.get(), nCount
);
1015 } while( nCount
== cBufLen
);
1020 SvStream
& SvStream::WriteUInt16( sal_uInt16 v
)
1024 writeNumberWithoutSwap(v
);
1028 SvStream
& SvStream::WriteUInt32( sal_uInt32 v
)
1032 writeNumberWithoutSwap(v
);
1036 SvStream
& SvStream::WriteUInt64( sal_uInt64 v
)
1040 writeNumberWithoutSwap(v
);
1044 SvStream
& SvStream::WriteInt16( sal_Int16 v
)
1048 writeNumberWithoutSwap(v
);
1052 SvStream
& SvStream::WriteInt32( sal_Int32 v
)
1056 writeNumberWithoutSwap(v
);
1060 SvStream
& SvStream::WriteInt64 (sal_Int64 v
)
1064 writeNumberWithoutSwap(v
);
1068 SvStream
& SvStream::WriteSChar( signed char v
)
1071 if (m_isIoWrite
&& sizeof(signed char) <= m_nBufFree
)
1074 m_pBufPos
++; // sizeof(char);
1076 if (m_nBufActualPos
> m_nBufActualLen
) // Append ?
1077 m_nBufActualLen
= m_nBufActualPos
;
1078 m_nBufFree
--; // = sizeof(char);
1082 WriteBytes( &v
, sizeof(signed char) );
1086 // Special treatment for Chars due to PutBack
1088 SvStream
& SvStream::WriteChar( char v
)
1091 if (m_isIoWrite
&& sizeof(char) <= m_nBufFree
)
1094 m_pBufPos
++; // sizeof(char);
1096 if (m_nBufActualPos
> m_nBufActualLen
) // Append ?
1097 m_nBufActualLen
= m_nBufActualPos
;
1098 m_nBufFree
--; // = sizeof(char);
1102 WriteBytes( &v
, sizeof(char) );
1106 SvStream
& SvStream::WriteUChar( unsigned char v
)
1109 if (m_isIoWrite
&& sizeof(char) <= m_nBufFree
)
1111 *reinterpret_cast<unsigned char*>(m_pBufPos
) = v
;
1112 m_pBufPos
++; // = sizeof(char);
1113 m_nBufActualPos
++; // = sizeof(char);
1114 if (m_nBufActualPos
> m_nBufActualLen
) // Append ?
1115 m_nBufActualLen
= m_nBufActualPos
;
1120 WriteBytes( &v
, sizeof(char) );
1124 SvStream
& SvStream::WriteUInt8( sal_uInt8 v
)
1126 return WriteUChar(v
);
1129 SvStream
& SvStream::WriteUnicode( sal_Unicode v
)
1131 return WriteUInt16(v
);
1134 SvStream
& SvStream::WriteFloat( float v
)
1140 writeNumberWithoutSwap(v
);
1144 SvStream
& SvStream::WriteDouble ( const double& r
)
1151 writeNumberWithoutSwap(nHelp
);
1157 writeNumberWithoutSwap(r
);
1162 SvStream
& SvStream::WriteCharPtr( const char* pBuf
)
1164 WriteBytes( pBuf
, strlen(pBuf
) );
1168 SvStream
& SvStream::WriteStream( SvStream
& rStream
)
1170 const sal_uInt32 cBufLen
= 0x8000;
1171 std::unique_ptr
<char[]> pBuf( new char[ cBufLen
] );
1174 nCount
= rStream
.ReadBytes( pBuf
.get(), cBufLen
);
1175 WriteBytes( pBuf
.get(), nCount
);
1176 } while( nCount
== cBufLen
);
1181 sal_uInt64
SvStream::WriteStream( SvStream
& rStream
, sal_uInt64 nSize
)
1183 const sal_uInt32 cBufLen
= 0x8000;
1184 std::unique_ptr
<char[]> pBuf( new char[ cBufLen
] );
1185 sal_uInt32 nCurBufLen
= cBufLen
;
1187 sal_uInt64 nWriteSize
= nSize
;
1191 nCurBufLen
= std::min
<sal_uInt64
>(nCurBufLen
, nWriteSize
);
1192 nCount
= rStream
.ReadBytes(pBuf
.get(), nCurBufLen
);
1193 WriteBytes( pBuf
.get(), nCount
);
1194 nWriteSize
-= nCount
;
1196 while( nWriteSize
&& nCount
== nCurBufLen
);
1198 return nSize
- nWriteSize
;
1201 OUString
SvStream::ReadUniOrByteString( rtl_TextEncoding eSrcCharSet
)
1203 // read UTF-16 string directly from stream ?
1204 if (eSrcCharSet
== RTL_TEXTENCODING_UNICODE
)
1205 return read_uInt32_lenPrefixed_uInt16s_ToOUString(*this);
1206 return read_uInt16_lenPrefixed_uInt8s_ToOUString(*this, eSrcCharSet
);
1209 SvStream
& SvStream::WriteUniOrByteString( const OUString
& rStr
, rtl_TextEncoding eDestCharSet
)
1211 // write UTF-16 string directly into stream ?
1212 if (eDestCharSet
== RTL_TEXTENCODING_UNICODE
)
1213 write_uInt32_lenPrefixed_uInt16s_FromOUString(*this, rStr
);
1215 write_uInt16_lenPrefixed_uInt8s_FromOUString(*this, rStr
, eDestCharSet
);
1219 void SvStream::FlushBuffer(bool isConsistent
)
1221 if (m_isDirty
&& isConsistent
) // Does stream require a flush?
1223 SeekPos(m_nBufFilePos
);
1225 CryptAndWriteBuffer(m_pRWBuf
.get(), m_nBufActualLen
);
1226 else if (PutData(m_pRWBuf
.get(), m_nBufActualLen
) != m_nBufActualLen
)
1227 SetError(SVSTREAM_WRITE_ERROR
);
1232 std::size_t SvStream::ReadBytes( void* pData
, std::size_t nCount
)
1234 std::size_t nSaveCount
= nCount
;
1235 if (!m_isConsistent
)
1240 nCount
= GetData( pData
,nCount
);
1242 EncryptBuffer(pData
, nCount
);
1243 m_nBufFilePos
+= nCount
;
1247 // check if block is completely within buffer
1249 m_isIoWrite
= false;
1250 if (nCount
<= static_cast<std::size_t>(m_nBufActualLen
- m_nBufActualPos
))
1254 memcpy(pData
, m_pBufPos
, static_cast<size_t>(nCount
));
1255 m_nBufActualPos
= m_nBufActualPos
+ static_cast<sal_uInt16
>(nCount
);
1256 m_pBufPos
+= nCount
;
1257 m_nBufFree
= m_nBufFree
- static_cast<sal_uInt16
>(nCount
);
1263 // Does data block fit into buffer?
1264 if (nCount
> m_nBufSize
)
1266 // => No! Thus read directly
1267 // into target area without using the buffer
1271 SeekPos(m_nBufFilePos
+ m_nBufActualPos
);
1272 m_nBufActualLen
= 0;
1273 m_pBufPos
= m_pRWBuf
.get();
1274 nCount
= GetData( pData
, nCount
);
1276 EncryptBuffer(pData
, nCount
);
1277 m_nBufFilePos
+= nCount
;
1278 m_nBufFilePos
+= m_nBufActualPos
;
1279 m_nBufActualPos
= 0;
1283 // => Yes. Fill buffer first, then copy to target area
1285 m_nBufFilePos
+= m_nBufActualPos
;
1286 SeekPos(m_nBufFilePos
);
1288 // TODO: Typecast before GetData, sal_uInt16 nCountTmp
1289 std::size_t nCountTmp
= GetData( m_pRWBuf
.get(), m_nBufSize
);
1291 EncryptBuffer(m_pRWBuf
.get(), nCountTmp
);
1292 m_nBufActualLen
= static_cast<sal_uInt16
>(nCountTmp
);
1293 if( nCount
> nCountTmp
)
1295 nCount
= nCountTmp
; // trim count back, EOF see below
1297 memcpy( pData
, m_pRWBuf
.get(), static_cast<size_t>(nCount
) );
1298 m_nBufActualPos
= static_cast<sal_uInt16
>(nCount
);
1299 m_pBufPos
= m_pRWBuf
.get() + nCount
;
1304 m_nBufFree
= m_nBufActualLen
- m_nBufActualPos
;
1305 if (nCount
!= nSaveCount
&& m_nError
!= ERRCODE_IO_PENDING
)
1307 if (nCount
== nSaveCount
&& m_nError
== ERRCODE_IO_PENDING
)
1308 m_nError
= ERRCODE_NONE
;
1312 std::size_t SvStream::WriteBytes( const void* pData
, std::size_t nCount
)
1319 SetError( ERRCODE_IO_CANTWRITE
);
1322 if (!m_isConsistent
)
1323 RefreshBuffer(); // Remove changes in buffer through PutBack
1328 nCount
= CryptAndWriteBuffer( pData
, nCount
);
1330 nCount
= PutData( pData
, nCount
);
1331 m_nBufFilePos
+= nCount
;
1337 if (nCount
<= static_cast<std::size_t>(m_nBufSize
- m_nBufActualPos
))
1339 memcpy( m_pBufPos
, pData
, static_cast<size_t>(nCount
) );
1340 m_nBufActualPos
= m_nBufActualPos
+ static_cast<sal_uInt16
>(nCount
);
1341 // Update length if buffer was updated
1342 if (m_nBufActualPos
> m_nBufActualLen
)
1343 m_nBufActualLen
= m_nBufActualPos
;
1345 m_pBufPos
+= nCount
;
1352 // Does data block fit into buffer?
1353 if (nCount
> m_nBufSize
)
1355 m_isIoWrite
= false;
1356 m_nBufFilePos
+= m_nBufActualPos
;
1357 m_nBufActualLen
= 0;
1358 m_nBufActualPos
= 0;
1359 m_pBufPos
= m_pRWBuf
.get();
1360 SeekPos(m_nBufFilePos
);
1362 nCount
= CryptAndWriteBuffer( pData
, nCount
);
1364 nCount
= PutData( pData
, nCount
);
1365 m_nBufFilePos
+= nCount
;
1369 // Copy block to buffer
1370 memcpy( m_pRWBuf
.get(), pData
, static_cast<size_t>(nCount
) );
1373 m_nBufFilePos
+= m_nBufActualPos
;
1374 m_nBufActualPos
= static_cast<sal_uInt16
>(nCount
);
1375 m_pBufPos
= m_pRWBuf
.get() + nCount
;
1376 m_nBufActualLen
= static_cast<sal_uInt16
>(nCount
);
1380 m_nBufFree
= m_nBufSize
- m_nBufActualPos
;
1384 sal_uInt64
SvStream::Seek(sal_uInt64
const nFilePos
)
1386 m_isIoRead
= m_isIoWrite
= false;
1390 m_nBufFilePos
= SeekPos( nFilePos
);
1391 DBG_ASSERT(Tell() == m_nBufFilePos
,"Out Of Sync!");
1392 return m_nBufFilePos
;
1395 // Is seek position within buffer?
1396 if (nFilePos
>= m_nBufFilePos
&& nFilePos
<= (m_nBufFilePos
+ m_nBufActualLen
))
1398 m_nBufActualPos
= static_cast<sal_uInt16
>(nFilePos
- m_nBufFilePos
);
1399 m_pBufPos
= m_pRWBuf
.get() + m_nBufActualPos
;
1400 // Update m_nBufFree to avoid crash upon PutBack
1401 m_nBufFree
= m_nBufActualLen
- m_nBufActualPos
;
1405 FlushBuffer(m_isConsistent
);
1406 m_nBufActualLen
= 0;
1407 m_nBufActualPos
= 0;
1408 m_pBufPos
= m_pRWBuf
.get();
1409 m_nBufFilePos
= SeekPos( nFilePos
);
1411 return m_nBufFilePos
+ m_nBufActualPos
;
1414 bool checkSeek(SvStream
&rSt
, sal_uInt64 nOffset
)
1416 const sal_uInt64
nMaxSeek(rSt
.Tell() + rSt
.remainingSize());
1417 return (nOffset
<= nMaxSeek
&& rSt
.Seek(nOffset
) == nOffset
);
1420 //STREAM_SEEK_TO_END in the some of the Seek backends is special cased to be
1421 //efficient, in others e.g. SotStorageStream it's really horribly slow, and in
1422 //those this should be overridden
1423 sal_uInt64
SvStream::remainingSize()
1425 sal_uInt64
const nCurr
= Tell();
1426 sal_uInt64
const nEnd
= Seek(STREAM_SEEK_TO_END
);
1427 sal_uInt64 nMaxAvailable
= nEnd
> nCurr
? (nEnd
-nCurr
) : 0;
1429 return nMaxAvailable
;
1432 void SvStream::Flush()
1434 FlushBuffer(m_isConsistent
);
1439 void SvStream::RefreshBuffer()
1441 FlushBuffer(m_isConsistent
);
1442 SeekPos(m_nBufFilePos
);
1443 m_nBufActualLen
= static_cast<sal_uInt16
>(GetData( m_pRWBuf
.get(), m_nBufSize
));
1444 if (m_nBufActualLen
&& m_nError
== ERRCODE_IO_PENDING
)
1445 m_nError
= ERRCODE_NONE
;
1447 EncryptBuffer(m_pRWBuf
.get(), static_cast<std::size_t>(m_nBufActualLen
));
1448 m_isConsistent
= true;
1449 m_isIoRead
= m_isIoWrite
= false;
1452 SvStream
& SvStream::WriteInt32AsString(sal_Int32 nInt32
)
1455 std::size_t nLen
= sprintf(buffer
, "%" SAL_PRIdINT32
, nInt32
);
1456 WriteBytes(buffer
, nLen
);
1460 SvStream
& SvStream::WriteUInt32AsString(sal_uInt32 nUInt32
)
1463 std::size_t nLen
= sprintf(buffer
, "%" SAL_PRIuUINT32
, nUInt32
);
1464 WriteBytes(buffer
, nLen
);
1468 #define CRYPT_BUFSIZE 1024
1470 /// Encrypt and write
1471 std::size_t SvStream::CryptAndWriteBuffer( const void* pStart
, std::size_t nLen
)
1473 unsigned char pTemp
[CRYPT_BUFSIZE
];
1474 unsigned char const * pDataPtr
= static_cast<unsigned char const *>(pStart
);
1475 std::size_t nCount
= 0;
1476 std::size_t nBufCount
;
1477 unsigned char nMask
= m_nCryptMask
;
1480 if( nLen
>= CRYPT_BUFSIZE
)
1481 nBufCount
= CRYPT_BUFSIZE
;
1485 memcpy( pTemp
, pDataPtr
, static_cast<sal_uInt16
>(nBufCount
) );
1486 // ******** Encrypt ********
1487 for (unsigned char & rn
: pTemp
)
1489 unsigned char aCh
= rn
;
1494 // *************************
1495 nCount
+= PutData( pTemp
, nBufCount
);
1496 pDataPtr
+= nBufCount
;
1502 bool SvStream::EncryptBuffer(void* pStart
, std::size_t nLen
) const
1504 unsigned char* pTemp
= static_cast<unsigned char*>(pStart
);
1505 unsigned char nMask
= m_nCryptMask
;
1507 for ( std::size_t n
=0; n
< nLen
; n
++, pTemp
++ )
1509 unsigned char aCh
= *pTemp
;
1517 static unsigned char implGetCryptMask(const sal_Char
* pStr
, sal_Int32 nLen
, long nVersion
)
1519 unsigned char nCryptMask
= 0;
1524 if( nVersion
<= SOFFICE_FILEFORMAT_31
)
1528 nCryptMask
^= *pStr
;
1533 else // BugFix #25888#
1535 for( sal_Int32 i
= 0; i
< nLen
; i
++ ) {
1536 nCryptMask
^= pStr
[i
];
1537 if( nCryptMask
& 0x80 ) {
1552 void SvStream::SetCryptMaskKey(const OString
& rCryptMaskKey
)
1554 m_aCryptMaskKey
= rCryptMaskKey
;
1555 m_nCryptMask
= implGetCryptMask(m_aCryptMaskKey
.getStr(),
1556 m_aCryptMaskKey
.getLength(), GetVersion());
1559 bool SvStream::SetStreamSize(sal_uInt64
const nSize
)
1562 sal_uInt64 nFPos
= Tell();
1564 sal_uInt16 nBuf
= m_nBufSize
;
1567 SetBufferSize( nBuf
);
1569 DBG_ASSERT(Tell()==nFPos
,"SetStreamSize failed");
1571 return (m_nError
== ERRCODE_NONE
);
1574 SvStream
& endl( SvStream
& rStr
)
1576 LineEnd eDelim
= rStr
.GetLineDelimiter();
1577 if ( eDelim
== LINEEND_CR
)
1578 rStr
.WriteChar('\r');
1579 else if( eDelim
== LINEEND_LF
)
1580 rStr
.WriteChar('\n');
1582 rStr
.WriteChar('\r').WriteChar('\n');
1586 SvStream
& endlu( SvStream
& rStrm
)
1588 switch ( rStrm
.GetLineDelimiter() )
1591 rStrm
.WriteUnicode('\r');
1594 rStrm
.WriteUnicode('\n');
1597 rStrm
.WriteUnicode('\r').WriteUnicode('\n');
1602 SvStream
& endlub( SvStream
& rStrm
)
1604 if ( rStrm
.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE
)
1605 return endlu( rStrm
);
1607 return endl( rStrm
);
1610 SvMemoryStream::SvMemoryStream( void* pBuffer
, std::size_t bufSize
,
1613 if( eMode
& StreamMode::WRITE
)
1614 m_isWritable
= true;
1616 m_isWritable
= false;
1617 nEndOfData
= bufSize
;
1619 pBuf
= static_cast<sal_uInt8
*>(pBuffer
);
1626 SvMemoryStream::SvMemoryStream( std::size_t nInitSize
, std::size_t nResizeOffset
)
1628 m_isWritable
= true;
1631 nResize
= nResizeOffset
;
1634 if( nResize
!= 0 && nResize
< 16 )
1636 if( nInitSize
&& !AllocateMemory( nInitSize
) )
1638 SetError( SVSTREAM_OUTOFMEMORY
);
1643 SetBufferSize( 64 );
1646 SvMemoryStream::~SvMemoryStream()
1657 const void* SvMemoryStream::GetBuffer()
1662 sal_uInt64
SvMemoryStream::GetSize()
1665 sal_uInt64
const nTemp
= Tell();
1666 sal_uInt64
const nLength
= Seek( STREAM_SEEK_TO_END
);
1671 void SvMemoryStream::SetBuffer( void* pNewBuf
, std::size_t nCount
,
1674 SetBufferSize( 0 ); // Init buffering in the base class
1678 if( pNewBuf
!= pBuf
)
1682 pBuf
= static_cast<sal_uInt8
*>(pNewBuf
);
1695 std::size_t SvMemoryStream::GetData( void* pData
, std::size_t nCount
)
1697 std::size_t nMaxCount
= nEndOfData
-nPos
;
1698 if( nCount
> nMaxCount
)
1702 memcpy( pData
, pBuf
+nPos
, static_cast<size_t>(nCount
) );
1708 std::size_t SvMemoryStream::PutData( const void* pData
, std::size_t nCount
)
1713 std::size_t nMaxCount
= nSize
-nPos
;
1715 // check for overflow
1716 if( nCount
> nMaxCount
)
1720 // copy as much as possible
1722 SetError( SVSTREAM_OUTOFMEMORY
);
1727 if( nSize
&& nSize
> nResize
)
1730 nNewResize
= nResize
;
1732 if( (nCount
-nMaxCount
) < nResize
)
1734 // lacking memory is smaller than nResize,
1735 // resize accordingly
1736 if( !ReAllocateMemory( nNewResize
) )
1739 SetError( SVSTREAM_WRITE_ERROR
);
1744 // lacking memory is larger than nResize,
1745 // resize by (nCount-nMaxCount) + resize offset
1746 if( !ReAllocateMemory( nCount
-nMaxCount
+nNewResize
) )
1749 SetError( SVSTREAM_WRITE_ERROR
);
1754 assert(pBuf
&& "Possibly Reallocate failed");
1755 memcpy( pBuf
+nPos
, pData
, static_cast<size_t>(nCount
));
1758 if( nPos
> nEndOfData
)
1763 sal_uInt64
SvMemoryStream::SeekPos(sal_uInt64
const nNewPos
)
1765 // nEndOfData: First position in stream not allowed to read from
1766 // nSize: Size of allocated buffer
1768 // check if a truncated STREAM_SEEK_TO_END was passed
1769 assert(nNewPos
!= SAL_MAX_UINT32
);
1770 if( nNewPos
< nEndOfData
)
1772 else if( nNewPos
== STREAM_SEEK_TO_END
)
1776 if( nNewPos
>= nSize
) // Does buffer need extension?
1778 if( nResize
) // Is extension possible?
1780 long nDiff
= static_cast<long>(nNewPos
- nSize
+ 1);
1781 nDiff
+= static_cast<long>(nResize
);
1782 ReAllocateMemory( nDiff
);
1784 nEndOfData
= nNewPos
;
1786 else // Extension not possible, set pos to end of data
1788 // SetError( SVSTREAM_OUTOFMEMORY );
1792 else // Expand buffer size
1795 nEndOfData
= nNewPos
;
1801 void SvMemoryStream::FlushData()
1805 void SvMemoryStream::ResetError()
1807 SvStream::ClearError();
1810 bool SvMemoryStream::AllocateMemory( std::size_t nNewSize
)
1812 pBuf
= new sal_uInt8
[nNewSize
];
1813 return( pBuf
!= nullptr );
1816 // (using Bozo algorithm)
1817 bool SvMemoryStream::ReAllocateMemory( long nDiff
)
1819 if (!m_isWritable
|| !bOwnsData
)
1822 bool bRetVal
= false;
1823 long nTemp
= static_cast<long>(nSize
);
1825 std::size_t nNewSize
= static_cast<std::size_t>(nTemp
);
1829 sal_uInt8
* pNewBuf
= new sal_uInt8
[nNewSize
];
1831 bRetVal
= true; // Success!
1832 if( nNewSize
< nSize
) // Are we shrinking?
1834 memcpy( pNewBuf
, pBuf
, static_cast<size_t>(nNewSize
) );
1835 if( nPos
> nNewSize
)
1837 if( nEndOfData
>= nNewSize
)
1838 nEndOfData
= nNewSize
-1;
1844 memcpy( pNewBuf
, pBuf
, static_cast<size_t>(nSize
) );
1846 memset(pNewBuf
+ nSize
, 0x00, nNewSize
- nSize
);
1867 void SvMemoryStream::FreeMemory()
1877 void* SvMemoryStream::SwitchBuffer()
1882 Seek( STREAM_SEEK_TO_BEGIN
);
1884 void* pRetVal
= pBuf
;
1890 if( nResize
!= 0 && nResize
< 16 )
1895 std::size_t nInitSize
= 512;
1896 if( !AllocateMemory(nInitSize
) )
1898 SetError( SVSTREAM_OUTOFMEMORY
);
1904 SetBufferSize( 64 );
1908 void SvMemoryStream::SetSize(sal_uInt64
const nNewSize
)
1912 SetError(SVSTREAM_INVALID_HANDLE
);
1916 long nDiff
= static_cast<long>(nNewSize
) - static_cast<long>(nSize
);
1917 ReAllocateMemory( nDiff
);
1920 //Create a OString of nLen bytes from rStream
1921 OString
read_uInt8s_ToOString(SvStream
& rStrm
, std::size_t nLen
)
1923 rtl_String
*pStr
= nullptr;
1926 nLen
= std::min
<std::size_t>(nLen
, SAL_MAX_INT32
);
1927 //limit allocation to size of file, but + 1 to set eof state
1928 nLen
= std::min
<sal_uInt64
>(nLen
, rStrm
.remainingSize() + 1);
1929 //alloc a (ref-count 1) rtl_String of the desired length.
1930 //rtl_String's buffer is uninitialized, except for null termination
1931 pStr
= rtl_string_alloc(sal::static_int_cast
<sal_Int32
>(nLen
));
1932 SAL_WARN_IF(!pStr
, "tools.stream", "allocation failed");
1935 std::size_t nWasRead
= rStrm
.ReadBytes(pStr
->buffer
, nLen
);
1936 if (nWasRead
!= nLen
)
1938 //on (typically unlikely) short read set length to what we could
1939 //read, and null terminate. Excess buffer capacity remains of
1940 //course, could create a (true) replacement OString if it matters.
1941 pStr
->length
= sal::static_int_cast
<sal_Int32
>(nWasRead
);
1942 pStr
->buffer
[pStr
->length
] = 0;
1947 //take ownership of buffer and return, otherwise return empty string
1948 return pStr
? OString(pStr
, SAL_NO_ACQUIRE
) : OString();
1951 //Create a OUString of nLen sal_Unicode code units from rStream
1952 OUString
read_uInt16s_ToOUString(SvStream
& rStrm
, std::size_t nLen
)
1954 rtl_uString
*pStr
= nullptr;
1957 nLen
= std::min
<std::size_t>(nLen
, SAL_MAX_INT32
);
1958 //limit allocation to size of file, but + 1 to set eof state
1959 nLen
= std::min
<sal_uInt64
>(nLen
, (rStrm
.remainingSize() + 2) / 2);
1960 //alloc a (ref-count 1) rtl_uString of the desired length.
1961 //rtl_String's buffer is uninitialized, except for null termination
1962 pStr
= rtl_uString_alloc(sal::static_int_cast
<sal_Int32
>(nLen
));
1963 SAL_WARN_IF(!pStr
, "tools.stream", "allocation failed");
1966 std::size_t nWasRead
= rStrm
.ReadBytes(pStr
->buffer
, nLen
*2)/2;
1967 if (nWasRead
!= nLen
)
1969 //on (typically unlikely) short read set length to what we could
1970 //read, and null terminate. Excess buffer capacity remains of
1971 //course, could create a (true) replacement OUString if it matters.
1972 pStr
->length
= sal::static_int_cast
<sal_Int32
>(nWasRead
);
1973 pStr
->buffer
[pStr
->length
] = 0;
1975 if (rStrm
.IsEndianSwap())
1977 for (sal_Int32 i
= 0; i
< pStr
->length
; ++i
)
1978 pStr
->buffer
[i
] = OSL_SWAPWORD(pStr
->buffer
[i
]);
1983 //take ownership of buffer and return, otherwise return empty string
1984 return pStr
? OUString(pStr
, SAL_NO_ACQUIRE
) : OUString();
1989 template <typename T
, typename O
> T
tmpl_convertLineEnd(const T
&rIn
, LineEnd eLineEnd
)
1991 // Determine linebreaks and compute length
1992 bool bConvert
= false; // Needs conversion
1993 sal_Int32 nStrLen
= rIn
.getLength();
1994 sal_Int32 nLineEndLen
= (eLineEnd
== LINEEND_CRLF
) ? 2 : 1;
1995 sal_Int32 nLen
= 0; // Target length
1996 sal_Int32 i
= 0; // Source counter
2000 // \r or \n causes linebreak
2001 if ( (rIn
[i
] == '\r') || (rIn
[i
] == '\n') )
2003 nLen
= nLen
+ nLineEndLen
;
2005 // If set already, skip expensive test
2008 // Do we need to convert?
2009 if ( ((eLineEnd
!= LINEEND_LF
) && (rIn
[i
] == '\n')) ||
2010 ((eLineEnd
== LINEEND_CRLF
) && (i
+1) < nStrLen
&& (rIn
[i
+1] != '\n')) ||
2011 ((eLineEnd
== LINEEND_LF
) &&
2012 ((rIn
[i
] == '\r') || ((i
+1) < nStrLen
&& rIn
[i
+1] == '\r'))) ||
2013 ((eLineEnd
== LINEEND_CR
) &&
2014 ((rIn
[i
] == '\n') || ((i
+1) < nStrLen
&& rIn
[i
+1] == '\n'))) )
2018 // skip char if \r\n or \n\r
2019 if ( (i
+1) < nStrLen
&& ((rIn
[i
+1] == '\r') || (rIn
[i
+1] == '\n')) &&
2020 (rIn
[i
] != rIn
[i
+1]) )
2031 // convert linebreaks, insert string
2036 // \r or \n causes linebreak
2037 if ( (rIn
[i
] == '\r') || (rIn
[i
] == '\n') )
2039 if ( eLineEnd
== LINEEND_CRLF
)
2041 aNewData
.append('\r');
2042 aNewData
.append('\n');
2046 if ( eLineEnd
== LINEEND_CR
)
2047 aNewData
.append('\r');
2049 aNewData
.append('\n');
2052 if ( (i
+1) < nStrLen
&& ((rIn
[i
+1] == '\r') || (rIn
[i
+1] == '\n')) &&
2053 (rIn
[i
] != rIn
[i
+1]) )
2058 aNewData
.append(rIn
[i
]);
2064 return aNewData
.makeStringAndClear();
2068 OString
convertLineEnd(const OString
&rIn
, LineEnd eLineEnd
)
2070 return tmpl_convertLineEnd
<OString
, OStringBuffer
>(rIn
, eLineEnd
);
2073 OUString
convertLineEnd(const OUString
&rIn
, LineEnd eLineEnd
)
2075 return tmpl_convertLineEnd
<OUString
, OUStringBuffer
>(rIn
, eLineEnd
);
2078 std::size_t write_uInt32_lenPrefixed_uInt16s_FromOUString(SvStream
& rStrm
,
2079 const OUString
&rStr
)
2081 std::size_t nWritten
= 0;
2082 sal_uInt32 nUnits
= std::min
<std::size_t>(rStr
.getLength(), std::numeric_limits
<sal_uInt32
>::max());
2083 SAL_WARN_IF(static_cast<std::size_t>(nUnits
) != static_cast<std::size_t>(rStr
.getLength()),
2085 "string too long for prefix count to fit in output type");
2086 rStrm
.WriteUInt32(nUnits
);
2089 nWritten
+= sizeof(sal_uInt32
);
2090 nWritten
+= write_uInt16s_FromOUString(rStrm
, rStr
, nUnits
);
2095 std::size_t write_uInt16_lenPrefixed_uInt16s_FromOUString(SvStream
& rStrm
,
2096 const OUString
&rStr
)
2098 std::size_t nWritten
= 0;
2099 sal_uInt16 nUnits
= std::min
<std::size_t>(rStr
.getLength(), std::numeric_limits
<sal_uInt16
>::max());
2100 SAL_WARN_IF(nUnits
!= rStr
.getLength(),
2102 "string too long for prefix count to fit in output type");
2103 rStrm
.WriteUInt16(nUnits
);
2106 nWritten
+= sizeof(nUnits
);
2107 nWritten
+= write_uInt16s_FromOUString(rStrm
, rStr
, nUnits
);
2112 std::size_t write_uInt16_lenPrefixed_uInt8s_FromOString(SvStream
& rStrm
,
2113 const OString
&rStr
)
2115 std::size_t nWritten
= 0;
2116 sal_uInt16 nUnits
= std::min
<std::size_t>(rStr
.getLength(), std::numeric_limits
<sal_uInt16
>::max());
2117 SAL_WARN_IF(static_cast<std::size_t>(nUnits
) != static_cast<std::size_t>(rStr
.getLength()),
2119 "string too long for sal_uInt16 count to fit in output type");
2120 rStrm
.WriteUInt16( nUnits
);
2123 nWritten
+= sizeof(sal_uInt16
);
2124 nWritten
+= write_uInt8s_FromOString(rStrm
, rStr
, nUnits
);
2129 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */