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
22 #include <sal/config.h>
30 #include <o3tl/safeint.hxx>
31 #include <osl/endian.h>
32 #include <osl/diagnose.h>
33 #include <rtl/strbuf.hxx>
34 #include <rtl/string.hxx>
35 #include <rtl/ustrbuf.hxx>
36 #include <sal/log.hxx>
37 #include <tools/long.hxx>
39 #include <comphelper/fileformat.h>
40 #include <comphelper/fileurl.hxx>
42 static void swapNibbles(unsigned char &c
)
44 unsigned char nSwapTmp
=c
;
50 #include <tools/debug.hxx>
51 #include <tools/stream.hxx>
52 #include <osl/thread.h>
55 // !!! Do not inline if already the operators <<,>> are inline
56 template <typename T
, std::enable_if_t
<std::is_integral_v
<T
> && sizeof(T
) == 2, int> = 0>
57 static void SwapNumber(T
& r
)
58 { r
= OSL_SWAPWORD(r
); }
59 template <typename T
, std::enable_if_t
<std::is_integral_v
<T
> && sizeof(T
) == 4, int> = 0>
60 static void SwapNumber(T
& r
)
61 { r
= OSL_SWAPDWORD(r
); }
62 template <typename T
, std::enable_if_t
<std::is_integral_v
<T
> && sizeof(T
) == 8, int> = 0>
63 static void SwapNumber(T
& r
)
72 std::swap(s
.c
[0], s
.c
[1]); // swap the 32 bit words
73 // swap the bytes in the words
74 s
.c
[0] = OSL_SWAPDWORD(s
.c
[0]);
75 s
.c
[1] = OSL_SWAPDWORD(s
.c
[1]);
80 static void SwapFloat( float& r
)
89 s
.c
= OSL_SWAPDWORD( s
.c
);
93 static void SwapDouble( double& r
)
95 if( sizeof(double) != 8 )
97 SAL_WARN( "tools.stream", "Can only swap 8-Byte-doubles" );
108 s
.c
[0] ^= s
.c
[1]; // swap 32-bit values in situ
111 s
.c
[0] = OSL_SWAPDWORD(s
.c
[0]); // swap dword itself in situ
112 s
.c
[1] = OSL_SWAPDWORD(s
.c
[1]);
120 void SvStream::readNumberWithoutSwap_(void * pDataDest
, int nDataSize
)
122 if (m_isIoRead
&& nDataSize
<= m_nBufFree
)
124 for (int i
= 0; i
< nDataSize
; i
++)
125 static_cast<char*>(pDataDest
)[i
] = m_pBufPos
[i
];
126 m_nBufActualPos
+= nDataSize
;
127 m_pBufPos
+= nDataSize
;
128 m_nBufFree
-= nDataSize
;
132 ReadBytes( pDataDest
, nDataSize
);
137 void SvStream::writeNumberWithoutSwap_(const void * pDataSrc
, int nDataSize
)
139 if (m_isIoWrite
&& nDataSize
<= m_nBufFree
)
141 for (int i
= 0; i
< nDataSize
; i
++)
142 m_pBufPos
[i
] = static_cast<const char*>(pDataSrc
)[i
];
143 m_nBufFree
-= nDataSize
;
144 m_nBufActualPos
+= nDataSize
;
145 if (m_nBufActualPos
> m_nBufActualLen
)
146 m_nBufActualLen
= m_nBufActualPos
;
147 m_pBufPos
+= nDataSize
;
152 WriteBytes( pDataSrc
, nDataSize
);
157 void SvLockBytes::close()
166 ErrCode
SvLockBytes::ReadAt(sal_uInt64
const nPos
, void * pBuffer
, std::size_t nCount
,
167 std::size_t * pRead
) const
171 OSL_FAIL("SvLockBytes::ReadAt(): Bad stream");
175 m_pStream
->Seek(nPos
);
176 std::size_t nTheRead
= m_pStream
->ReadBytes(pBuffer
, nCount
);
179 return m_pStream
->GetErrorCode();
183 ErrCode
SvLockBytes::WriteAt(sal_uInt64
const nPos
, const void * pBuffer
, std::size_t nCount
,
184 std::size_t * pWritten
)
188 OSL_FAIL("SvLockBytes::WriteAt(): Bad stream");
192 m_pStream
->Seek(nPos
);
193 std::size_t nTheWritten
= m_pStream
->WriteBytes(pBuffer
, nCount
);
195 *pWritten
= nTheWritten
;
196 return m_pStream
->GetErrorCode();
200 ErrCode
SvLockBytes::Flush() const
204 OSL_FAIL("SvLockBytes::Flush(): Bad stream");
209 return m_pStream
->GetErrorCode();
213 ErrCode
SvLockBytes::SetSize(sal_uInt64
const nSize
)
217 OSL_FAIL("SvLockBytes::SetSize(): Bad stream");
221 m_pStream
->SetStreamSize(nSize
);
222 return m_pStream
->GetErrorCode();
225 ErrCode
SvLockBytes::Stat(SvLockBytesStat
* pStat
) const
229 OSL_FAIL("SvLockBytes::Stat(): Bad stream");
234 pStat
->nSize
= m_pStream
->TellEnd();
239 std::size_t SvStream::GetData( void* pData
, std::size_t nSize
)
243 DBG_ASSERT( m_xLockBytes
.is(), "pure virtual function" );
245 m_nError
= m_xLockBytes
->ReadAt(m_nActPos
, pData
, nSize
, &nRet
);
252 std::size_t SvStream::PutData( const void* pData
, std::size_t nSize
)
256 DBG_ASSERT( m_xLockBytes
.is(), "pure virtual function" );
258 m_nError
= m_xLockBytes
->WriteAt(m_nActPos
, pData
, nSize
, &nRet
);
265 sal_uInt64
SvStream::SeekPos(sal_uInt64
const nPos
)
267 // check if a truncated STREAM_SEEK_TO_END was passed
268 assert(nPos
!= SAL_MAX_UINT32
);
269 if( !GetError() && nPos
== STREAM_SEEK_TO_END
)
271 DBG_ASSERT( m_xLockBytes
.is(), "pure virtual function" );
272 SvLockBytesStat aStat
;
273 m_xLockBytes
->Stat( &aStat
);
274 m_nActPos
= aStat
.nSize
;
281 void SvStream::FlushData()
285 DBG_ASSERT( m_xLockBytes
.is(), "pure virtual function" );
286 m_nError
= m_xLockBytes
->Flush();
290 void SvStream::SetSize(sal_uInt64
const nSize
)
292 DBG_ASSERT( m_xLockBytes
.is(), "pure virtual function" );
293 m_nError
= m_xLockBytes
->SetSize( nSize
);
296 SvStream::SvStream() :
310 , m_nCompressMode(SvStreamCompressFlags::NONE
)
312 , m_eLineDelimiter(LINEEND_LF
) // UNIX-Format
314 , m_eLineDelimiter(LINEEND_CRLF
) // DOS-Format
316 , m_eStreamCharSet(osl_getThreadTextEncoding())
323 , m_eStreamMode(StreamMode::NONE
)
327 SetEndian( SvStreamEndian::LITTLE
);
332 SvStream::SvStream( SvLockBytes
* pLockBytesP
) : SvStream()
334 m_xLockBytes
= pLockBytesP
;
336 const SvStream
* pStrm
= pLockBytesP
->GetStream();
338 SetError( pStrm
->GetErrorCode() );
341 SetBufferSize( 256 );
344 SvStream::~SvStream()
346 if (m_xLockBytes
.is())
350 void SvStream::ClearError()
353 m_nError
= ERRCODE_NONE
;
356 void SvStream::SetError( ErrCode nErrorCode
)
358 if (m_nError
== ERRCODE_NONE
)
359 m_nError
= nErrorCode
;
362 void SvStream::SetEndian( SvStreamEndian nNewFormat
)
365 m_isSwap
= nNewFormat
== SvStreamEndian::LITTLE
;
367 m_isSwap
= nNewFormat
== SvStreamEndian::BIG
;
371 SvStreamEndian
SvStream::GetEndian() const
374 return m_isSwap
? SvStreamEndian::LITTLE
: SvStreamEndian::BIG
;
376 return m_isSwap
? SvStreamEndian::BIG
: SvStreamEndian::LITTLE
;
380 void SvStream::SetBufferSize( sal_uInt16 nBufferSize
)
382 sal_uInt64
const nActualFilePos
= Tell();
383 bool bDontSeek
= (m_pRWBuf
== nullptr);
385 if (m_isDirty
&& m_isWritable
) // due to Windows NT: Access denied
391 m_nBufFilePos
+= m_nBufActualPos
;
397 m_nBufSize
= nBufferSize
;
399 m_pRWBuf
.reset(new sal_uInt8
[ m_nBufSize
]);
400 m_pBufPos
= m_pRWBuf
.get();
401 m_isIoRead
= m_isIoWrite
= false;
403 SeekPos( nActualFilePos
);
406 void SvStream::ClearBuffer()
411 m_pBufPos
= m_pRWBuf
.get();
413 m_isIoRead
= m_isIoWrite
= false;
418 void SvStream::ResetError()
423 bool SvStream::ReadByteStringLine( OUString
& rStr
, rtl_TextEncoding eSrcCharSet
,
424 sal_Int32 nMaxBytesToRead
)
427 bool bRet
= ReadLine( aStr
, nMaxBytesToRead
);
428 rStr
= OStringToOUString(aStr
, eSrcCharSet
);
432 bool SvStream::ReadLine( OString
& rStr
, sal_Int32 nMaxBytesToRead
)
434 OStringBuffer
aBuf(4096);
435 bool rv
= ReadLine(aBuf
, nMaxBytesToRead
);
436 rStr
= aBuf
.makeStringAndClear();
440 bool SvStream::ReadLine( OStringBuffer
& aBuf
, sal_Int32 nMaxBytesToRead
)
444 sal_uInt64 nOldFilePos
= Tell();
446 std::size_t nTotalLen
= 0;
449 while( !bEnd
&& !GetError() ) // Don't test for EOF as we
450 // are reading block-wise!
452 sal_uInt16 nLen
= static_cast<sal_uInt16
>(ReadBytes(buf
, sizeof(buf
)-1));
455 if ( aBuf
.isEmpty() )
457 // Exit on first block-read error
467 for( j
= n
= 0; j
< nLen
; ++j
)
470 if ( c
== '\n' || c
== '\r' )
480 if (nTotalLen
> o3tl::make_unsigned(nMaxBytesToRead
))
482 n
-= nTotalLen
- nMaxBytesToRead
;
483 nTotalLen
= nMaxBytesToRead
;
490 if ( !bEnd
&& !GetError() && !aBuf
.isEmpty() )
493 nOldFilePos
+= nTotalLen
;
494 if( Tell() > nOldFilePos
)
496 Seek( nOldFilePos
); // Seek pointer due to BlockRead above
498 if ( bEnd
&& (c
=='\r' || c
=='\n') ) // Special treatment for DOS files
501 std::size_t nLen
= ReadBytes(&cTemp
, sizeof(cTemp
));
503 if( cTemp
== c
|| (cTemp
!= '\n' && cTemp
!= '\r') )
513 bool SvStream::ReadUniStringLine( OUString
& rStr
, sal_Int32 nMaxCodepointsToRead
)
515 sal_Unicode buf
[256+1];
517 sal_uInt64 nOldFilePos
= Tell();
519 std::size_t nTotalLen
= 0;
521 DBG_ASSERT( sizeof(sal_Unicode
) == sizeof(sal_uInt16
), "ReadUniStringLine: swapping sizeof(sal_Unicode) not implemented" );
523 OUStringBuffer
aBuf(4096);
524 while( !bEnd
&& !GetError() ) // Don't test for EOF as we
525 // are reading block-wise!
527 sal_uInt16 nLen
= static_cast<sal_uInt16
>(ReadBytes( buf
, sizeof(buf
)-sizeof(sal_Unicode
)));
528 nLen
/= sizeof(sal_Unicode
);
531 if ( aBuf
.isEmpty() )
533 // exit on first BlockRead error
543 for( j
= n
= 0; j
< nLen
; ++j
)
546 SwapNumber( buf
[n
] );
548 if ( c
== '\n' || c
== '\r' )
553 // erAck 26.02.01: Old behavior was no special treatment of '\0'
554 // character here, but a following rStr+=c did ignore it. Is this
555 // really intended? Or should a '\0' better terminate a line?
556 // The nOldFilePos stuff wasn't correct then anyways.
565 if (nTotalLen
> o3tl::make_unsigned(nMaxCodepointsToRead
))
567 n
-= nTotalLen
- nMaxCodepointsToRead
;
568 nTotalLen
= nMaxCodepointsToRead
;
572 aBuf
.append( buf
, n
);
575 if ( !bEnd
&& !GetError() && !aBuf
.isEmpty() )
578 nOldFilePos
+= nTotalLen
* sizeof(sal_Unicode
);
579 if( Tell() > nOldFilePos
)
580 nOldFilePos
+= sizeof(sal_Unicode
);
581 Seek( nOldFilePos
); // seek due to BlockRead above
583 if ( bEnd
&& (c
=='\r' || c
=='\n') ) // special treatment for DOS files
586 ReadBytes( &cTemp
, sizeof(cTemp
) );
589 if( cTemp
== c
|| (cTemp
!= '\n' && cTemp
!= '\r') )
595 rStr
= aBuf
.makeStringAndClear();
599 bool SvStream::ReadUniOrByteStringLine( OUString
& rStr
, rtl_TextEncoding eSrcCharSet
,
600 sal_Int32 nMaxCodepointsToRead
)
602 if ( eSrcCharSet
== RTL_TEXTENCODING_UNICODE
)
603 return ReadUniStringLine( rStr
, nMaxCodepointsToRead
);
605 return ReadByteStringLine( rStr
, eSrcCharSet
, nMaxCodepointsToRead
);
608 OString
read_zeroTerminated_uInt8s_ToOString(SvStream
& rStream
)
610 OStringBuffer
aOutput(256);
614 sal_uInt64 nFilePos
= rStream
.Tell();
616 while( !bEnd
&& !rStream
.GetError() )
618 std::size_t nLen
= rStream
.ReadBytes(buf
, sizeof(buf
)-1);
622 std::size_t nReallyRead
= nLen
;
623 const char* pPtr
= buf
;
624 while (nLen
&& *pPtr
)
630 bEnd
= ( nReallyRead
< sizeof(buf
)-1 ) // read less than attempted to read
631 || ( ( nLen
> 0 ) // OR it is inside the block we read
632 && ( 0 == *pPtr
) // AND found a string terminator
635 aOutput
.append(buf
, pPtr
- buf
);
638 nFilePos
+= aOutput
.getLength();
639 if (rStream
.Tell() > nFilePos
)
640 rStream
.Seek(nFilePos
+1); // seek due to FileRead above
641 return aOutput
.makeStringAndClear();
644 OUString
read_zeroTerminated_uInt8s_ToOUString(SvStream
& rStream
, rtl_TextEncoding eEnc
)
646 return OStringToOUString(
647 read_zeroTerminated_uInt8s_ToOString(rStream
), eEnc
);
650 /** Attempt to write a prefixed sequence of nUnits 16bit units from an OUString,
651 returned value is number of bytes written */
652 std::size_t write_uInt16s_FromOUString(SvStream
& rStrm
, std::u16string_view rStr
,
655 DBG_ASSERT( sizeof(sal_Unicode
) == sizeof(sal_uInt16
), "write_uInt16s_FromOUString: swapping sizeof(sal_Unicode) not implemented" );
656 std::size_t nWritten
;
657 if (!rStrm
.IsEndianSwap())
658 nWritten
= rStrm
.WriteBytes(rStr
.data(), nUnits
* sizeof(sal_Unicode
));
661 std::size_t nLen
= nUnits
;
662 sal_Unicode aBuf
[384];
663 sal_Unicode
* const pTmp
= ( nLen
> 384 ? new sal_Unicode
[nLen
] : aBuf
);
664 memcpy( pTmp
, rStr
.data(), nLen
* sizeof(sal_Unicode
) );
665 sal_Unicode
* p
= pTmp
;
666 const sal_Unicode
* const pStop
= pTmp
+ nLen
;
672 nWritten
= rStrm
.WriteBytes( pTmp
, nLen
* sizeof(sal_Unicode
) );
679 bool SvStream::WriteUnicodeOrByteText( std::u16string_view rStr
, rtl_TextEncoding eDestCharSet
)
681 if ( eDestCharSet
== RTL_TEXTENCODING_UNICODE
)
683 write_uInt16s_FromOUString(*this, rStr
, rStr
.size());
684 return m_nError
== ERRCODE_NONE
;
688 OString
aStr(OUStringToOString(rStr
, eDestCharSet
));
689 write_uInt8s_FromOString(*this, aStr
, aStr
.getLength());
690 return m_nError
== ERRCODE_NONE
;
694 bool SvStream::WriteByteStringLine( std::u16string_view rStr
, rtl_TextEncoding eDestCharSet
)
696 return WriteLine(OUStringToOString(rStr
, eDestCharSet
));
699 bool SvStream::WriteLine(std::string_view rStr
)
701 WriteBytes(rStr
.data(), rStr
.size());
703 return m_nError
== ERRCODE_NONE
;
706 bool SvStream::WriteUniOrByteChar( sal_Unicode ch
, rtl_TextEncoding eDestCharSet
)
708 if ( eDestCharSet
== RTL_TEXTENCODING_UNICODE
)
712 OString
aStr(&ch
, 1, eDestCharSet
);
713 WriteBytes(aStr
.getStr(), aStr
.getLength());
715 return m_nError
== ERRCODE_NONE
;
718 void SvStream::StartWritingUnicodeText()
720 m_isSwap
= false; // Switch to no endian swapping
721 // BOM, Byte Order Mark, U+FEFF, see
722 // http://www.unicode.org/faq/utf_bom.html#BOM
723 // Upon read: 0xfeff(-257) => no swap; 0xfffe(-2) => swap
727 void SvStream::StartReadingUnicodeText( rtl_TextEncoding eReadBomCharSet
)
729 if (!( eReadBomCharSet
== RTL_TEXTENCODING_DONTKNOW
||
730 eReadBomCharSet
== RTL_TEXTENCODING_UNICODE
||
731 eReadBomCharSet
== RTL_TEXTENCODING_UTF8
))
732 return; // nothing to read
734 const sal_uInt64 nOldPos
= Tell();
735 bool bGetBack
= true;
736 unsigned char nFlag(0);
740 case 0xfe: // UTF-16BE?
741 if ( eReadBomCharSet
== RTL_TEXTENCODING_DONTKNOW
||
742 eReadBomCharSet
== RTL_TEXTENCODING_UNICODE
)
747 SetEndian(SvStreamEndian::BIG
);
752 case 0xff: // UTF-16LE?
753 if ( eReadBomCharSet
== RTL_TEXTENCODING_DONTKNOW
||
754 eReadBomCharSet
== RTL_TEXTENCODING_UNICODE
)
759 SetEndian(SvStreamEndian::LITTLE
);
765 if ( eReadBomCharSet
== RTL_TEXTENCODING_DONTKNOW
||
766 eReadBomCharSet
== RTL_TEXTENCODING_UTF8
)
773 bGetBack
= false; // it is UTF-8
781 Seek(nOldPos
); // no BOM, pure data
784 sal_uInt64
SvStream::SeekRel(sal_Int64
const nPos
)
786 sal_uInt64 nActualPos
= Tell();
790 if (SAL_MAX_UINT64
- nActualPos
> o3tl::make_unsigned(nPos
))
795 sal_uInt64
const nAbsPos
= static_cast<sal_uInt64
>(-nPos
);
796 if ( nActualPos
>= nAbsPos
)
797 nActualPos
-= nAbsPos
;
800 assert((m_pBufPos
!= nullptr) == bool(m_pRWBuf
));
803 m_pBufPos
= m_pRWBuf
.get() + nActualPos
;
805 return Seek( nActualPos
);
808 template <typename T
> SvStream
& SvStream::ReadNumber(T
& r
)
811 readNumberWithoutSwap(n
);
821 SvStream
& SvStream::ReadUInt16(sal_uInt16
& r
) { return ReadNumber(r
); }
822 SvStream
& SvStream::ReadUInt32(sal_uInt32
& r
) { return ReadNumber(r
); }
823 SvStream
& SvStream::ReadUInt64(sal_uInt64
& r
) { return ReadNumber(r
); }
824 SvStream
& SvStream::ReadInt16(sal_Int16
& r
) { return ReadNumber(r
); }
825 SvStream
& SvStream::ReadInt32(sal_Int32
& r
) { return ReadNumber(r
); }
826 SvStream
& SvStream::ReadInt64(sal_Int64
& r
) { return ReadNumber(r
); }
828 SvStream
& SvStream::ReadSChar( signed char& r
)
830 if (m_isIoRead
&& sizeof(signed char) <= m_nBufFree
)
833 m_nBufActualPos
+= sizeof(signed char);
834 m_pBufPos
+= sizeof(signed char);
835 m_nBufFree
-= sizeof(signed char);
838 ReadBytes( &r
, sizeof(signed char) );
842 // Special treatment for Chars due to PutBack
844 SvStream
& SvStream::ReadChar( char& r
)
846 if (m_isIoRead
&& sizeof(char) <= m_nBufFree
)
849 m_nBufActualPos
+= sizeof(char);
850 m_pBufPos
+= sizeof(char);
851 m_nBufFree
-= sizeof(char);
854 ReadBytes( &r
, sizeof(char) );
858 SvStream
& SvStream::ReadUChar( unsigned char& r
)
860 if (m_isIoRead
&& sizeof(char) <= m_nBufFree
)
863 m_nBufActualPos
+= sizeof(char);
864 m_pBufPos
+= sizeof(char);
865 m_nBufFree
-= sizeof(char);
868 ReadBytes( &r
, sizeof(char) );
872 SvStream
& SvStream::ReadUtf16(sal_Unicode
& r
) { return ReadNumber(r
); }
874 SvStream
& SvStream::ReadCharAsBool( bool& r
)
876 if (m_isIoRead
&& sizeof(char) <= m_nBufFree
)
879 *m_pBufPos
> 1, "tools.stream", unsigned(*m_pBufPos
) << " not 0/1");
881 m_nBufActualPos
+= sizeof(char);
882 m_pBufPos
+= sizeof(char);
883 m_nBufFree
-= sizeof(char);
888 if (ReadBytes(&c
, 1) == 1)
890 SAL_WARN_IF(c
> 1, "tools.stream", unsigned(c
) << " not 0/1");
897 SvStream
& SvStream::ReadFloat(float& r
)
900 readNumberWithoutSwap(n
);
912 SvStream
& SvStream::ReadDouble(double& r
)
915 readNumberWithoutSwap(n
);
927 SvStream
& SvStream::ReadStream( SvStream
& rStream
)
929 const sal_uInt32 cBufLen
= 0x8000;
930 std::unique_ptr
<char[]> pBuf( new char[ cBufLen
] );
934 nCount
= ReadBytes( pBuf
.get(), cBufLen
);
935 rStream
.WriteBytes( pBuf
.get(), nCount
);
936 } while( nCount
== cBufLen
);
941 template <typename T
> SvStream
& SvStream::WriteNumber(T n
)
945 writeNumberWithoutSwap(n
);
949 SvStream
& SvStream::WriteUInt16(sal_uInt16 v
) { return WriteNumber(v
); }
950 SvStream
& SvStream::WriteUInt32(sal_uInt32 v
) { return WriteNumber(v
); }
951 SvStream
& SvStream::WriteUInt64(sal_uInt64 v
) { return WriteNumber(v
); }
952 SvStream
& SvStream::WriteInt16(sal_Int16 v
) { return WriteNumber(v
); }
953 SvStream
& SvStream::WriteInt32(sal_Int32 v
) { return WriteNumber(v
); }
954 SvStream
& SvStream::WriteInt64(sal_Int64 v
) { return WriteNumber(v
); }
956 SvStream
& SvStream::WriteSChar( signed char v
)
959 if (m_isIoWrite
&& sizeof(signed char) <= m_nBufFree
)
962 m_pBufPos
++; // sizeof(char);
964 if (m_nBufActualPos
> m_nBufActualLen
) // Append ?
965 m_nBufActualLen
= m_nBufActualPos
;
966 m_nBufFree
--; // = sizeof(char);
970 WriteBytes( &v
, sizeof(signed char) );
974 // Special treatment for Chars due to PutBack
976 SvStream
& SvStream::WriteChar( char v
)
979 if (m_isIoWrite
&& sizeof(char) <= m_nBufFree
)
982 m_pBufPos
++; // sizeof(char);
984 if (m_nBufActualPos
> m_nBufActualLen
) // Append ?
985 m_nBufActualLen
= m_nBufActualPos
;
986 m_nBufFree
--; // = sizeof(char);
990 WriteBytes( &v
, sizeof(char) );
994 SvStream
& SvStream::WriteUChar( unsigned char v
)
997 if (m_isIoWrite
&& sizeof(char) <= m_nBufFree
)
999 *reinterpret_cast<unsigned char*>(m_pBufPos
) = v
;
1000 m_pBufPos
++; // = sizeof(char);
1001 m_nBufActualPos
++; // = sizeof(char);
1002 if (m_nBufActualPos
> m_nBufActualLen
) // Append ?
1003 m_nBufActualLen
= m_nBufActualPos
;
1008 WriteBytes( &v
, sizeof(char) );
1012 SvStream
& SvStream::WriteUInt8( sal_uInt8 v
)
1014 return WriteUChar(v
);
1017 SvStream
& SvStream::WriteUnicode( sal_Unicode v
)
1019 return WriteUInt16(v
);
1022 SvStream
& SvStream::WriteFloat( float v
)
1028 writeNumberWithoutSwap(v
);
1032 SvStream
& SvStream::WriteDouble ( const double& r
)
1039 writeNumberWithoutSwap(nHelp
);
1045 writeNumberWithoutSwap(r
);
1050 SvStream
& SvStream::WriteStream( SvStream
& rStream
)
1052 const sal_uInt32 cBufLen
= 0x8000;
1053 std::unique_ptr
<char[]> pBuf( new char[ cBufLen
] );
1056 nCount
= rStream
.ReadBytes( pBuf
.get(), cBufLen
);
1057 WriteBytes( pBuf
.get(), nCount
);
1058 } while( nCount
== cBufLen
);
1063 sal_uInt64
SvStream::WriteStream( SvStream
& rStream
, sal_uInt64 nSize
)
1065 const sal_uInt32 cBufLen
= 0x8000;
1066 std::unique_ptr
<char[]> pBuf( new char[ cBufLen
] );
1067 sal_uInt32 nCurBufLen
= cBufLen
;
1069 sal_uInt64 nWriteSize
= nSize
;
1073 nCurBufLen
= std::min
<sal_uInt64
>(nCurBufLen
, nWriteSize
);
1074 nCount
= rStream
.ReadBytes(pBuf
.get(), nCurBufLen
);
1075 WriteBytes( pBuf
.get(), nCount
);
1076 nWriteSize
-= nCount
;
1078 while( nWriteSize
&& nCount
== nCurBufLen
);
1080 return nSize
- nWriteSize
;
1083 OUString
SvStream::ReadUniOrByteString( rtl_TextEncoding eSrcCharSet
)
1085 // read UTF-16 string directly from stream ?
1086 if (eSrcCharSet
== RTL_TEXTENCODING_UNICODE
)
1087 return read_uInt32_lenPrefixed_uInt16s_ToOUString(*this);
1088 return read_uInt16_lenPrefixed_uInt8s_ToOUString(*this, eSrcCharSet
);
1091 SvStream
& SvStream::WriteUniOrByteString( std::u16string_view rStr
, rtl_TextEncoding eDestCharSet
)
1093 // write UTF-16 string directly into stream ?
1094 if (eDestCharSet
== RTL_TEXTENCODING_UNICODE
)
1095 write_uInt32_lenPrefixed_uInt16s_FromOUString(*this, rStr
);
1097 write_uInt16_lenPrefixed_uInt8s_FromOUString(*this, rStr
, eDestCharSet
);
1101 void SvStream::FlushBuffer()
1103 if (m_isDirty
) // Does stream require a flush?
1105 SeekPos(m_nBufFilePos
);
1107 CryptAndWriteBuffer(m_pRWBuf
.get(), m_nBufActualLen
);
1108 else if (PutData(m_pRWBuf
.get(), m_nBufActualLen
) != m_nBufActualLen
)
1109 SetError(SVSTREAM_WRITE_ERROR
);
1114 std::size_t SvStream::ReadBytes( void* pData
, std::size_t nCount
)
1116 std::size_t nSaveCount
= nCount
;
1120 nCount
= GetData( pData
,nCount
);
1122 EncryptBuffer(pData
, nCount
);
1123 m_nBufFilePos
+= nCount
;
1127 // check if block is completely within buffer
1129 m_isIoWrite
= false;
1130 if (nCount
<= o3tl::make_unsigned(m_nBufActualLen
- m_nBufActualPos
))
1134 memcpy(pData
, m_pBufPos
, nCount
);
1135 m_nBufActualPos
= m_nBufActualPos
+ static_cast<sal_uInt16
>(nCount
);
1136 m_pBufPos
+= nCount
;
1137 m_nBufFree
= m_nBufFree
- static_cast<sal_uInt16
>(nCount
);
1143 // Does data block fit into buffer?
1144 if (nCount
> m_nBufSize
)
1146 // => No! Thus read directly
1147 // into target area without using the buffer
1151 SeekPos(m_nBufFilePos
+ m_nBufActualPos
);
1152 m_nBufActualLen
= 0;
1153 m_pBufPos
= m_pRWBuf
.get();
1154 nCount
= GetData( pData
, nCount
);
1156 EncryptBuffer(pData
, nCount
);
1157 m_nBufFilePos
+= nCount
;
1158 m_nBufFilePos
+= m_nBufActualPos
;
1159 m_nBufActualPos
= 0;
1163 // => Yes. Fill buffer first, then copy to target area
1165 m_nBufFilePos
+= m_nBufActualPos
;
1166 SeekPos(m_nBufFilePos
);
1168 // TODO: Typecast before GetData, sal_uInt16 nCountTmp
1169 std::size_t nCountTmp
= GetData( m_pRWBuf
.get(), m_nBufSize
);
1171 EncryptBuffer(m_pRWBuf
.get(), nCountTmp
);
1172 m_nBufActualLen
= static_cast<sal_uInt16
>(nCountTmp
);
1173 if( nCount
> nCountTmp
)
1175 nCount
= nCountTmp
; // trim count back, EOF see below
1177 memcpy( pData
, m_pRWBuf
.get(), nCount
);
1178 m_nBufActualPos
= static_cast<sal_uInt16
>(nCount
);
1179 m_pBufPos
= m_pRWBuf
.get() + nCount
;
1184 m_nBufFree
= m_nBufActualLen
- m_nBufActualPos
;
1185 if (nCount
!= nSaveCount
&& m_nError
!= ERRCODE_IO_PENDING
)
1187 if (nCount
== nSaveCount
&& m_nError
== ERRCODE_IO_PENDING
)
1188 m_nError
= ERRCODE_NONE
;
1192 std::size_t SvStream::WriteBytes( const void* pData
, std::size_t nCount
)
1199 SetError( ERRCODE_IO_CANTWRITE
);
1206 nCount
= CryptAndWriteBuffer( pData
, nCount
);
1208 nCount
= PutData( pData
, nCount
);
1209 m_nBufFilePos
+= nCount
;
1215 if (nCount
<= o3tl::make_unsigned(m_nBufSize
- m_nBufActualPos
))
1217 memcpy( m_pBufPos
, pData
, nCount
);
1218 m_nBufActualPos
= m_nBufActualPos
+ static_cast<sal_uInt16
>(nCount
);
1219 // Update length if buffer was updated
1220 if (m_nBufActualPos
> m_nBufActualLen
)
1221 m_nBufActualLen
= m_nBufActualPos
;
1223 m_pBufPos
+= nCount
;
1230 // Does data block fit into buffer?
1231 if (nCount
> m_nBufSize
)
1233 m_isIoWrite
= false;
1234 m_nBufFilePos
+= m_nBufActualPos
;
1235 m_nBufActualLen
= 0;
1236 m_nBufActualPos
= 0;
1237 m_pBufPos
= m_pRWBuf
.get();
1238 SeekPos(m_nBufFilePos
);
1240 nCount
= CryptAndWriteBuffer( pData
, nCount
);
1242 nCount
= PutData( pData
, nCount
);
1243 m_nBufFilePos
+= nCount
;
1247 // Copy block to buffer
1248 memcpy( m_pRWBuf
.get(), pData
, nCount
);
1251 m_nBufFilePos
+= m_nBufActualPos
;
1252 m_nBufActualPos
= static_cast<sal_uInt16
>(nCount
);
1253 m_pBufPos
= m_pRWBuf
.get() + nCount
;
1254 m_nBufActualLen
= static_cast<sal_uInt16
>(nCount
);
1258 m_nBufFree
= m_nBufSize
- m_nBufActualPos
;
1262 sal_uInt64
SvStream::Seek(sal_uInt64
const nFilePos
)
1264 m_isIoRead
= m_isIoWrite
= false;
1268 m_nBufFilePos
= SeekPos( nFilePos
);
1269 DBG_ASSERT(Tell() == m_nBufFilePos
,"Out Of Sync!");
1270 return m_nBufFilePos
;
1273 // Is seek position within buffer?
1274 if (nFilePos
>= m_nBufFilePos
&& nFilePos
<= (m_nBufFilePos
+ m_nBufActualLen
))
1276 m_nBufActualPos
= static_cast<sal_uInt16
>(nFilePos
- m_nBufFilePos
);
1277 m_pBufPos
= m_pRWBuf
.get() + m_nBufActualPos
;
1278 // Update m_nBufFree to avoid crash upon PutBack
1279 m_nBufFree
= m_nBufActualLen
- m_nBufActualPos
;
1284 m_nBufActualLen
= 0;
1285 m_nBufActualPos
= 0;
1286 m_pBufPos
= m_pRWBuf
.get();
1287 m_nBufFilePos
= SeekPos( nFilePos
);
1289 return m_nBufFilePos
+ m_nBufActualPos
;
1292 bool checkSeek(SvStream
&rSt
, sal_uInt64 nOffset
)
1294 const sal_uInt64 nMaxSeek
= rSt
.TellEnd();
1295 return (nOffset
<= nMaxSeek
&& rSt
.Seek(nOffset
) == nOffset
);
1300 bool isEmptyFileUrl(const OUString
& rUrl
)
1302 if (!comphelper::isFileUrl(rUrl
))
1307 SvFileStream
aStream(rUrl
, StreamMode::READ
);
1308 if (!aStream
.IsOpen())
1313 return aStream
.remainingSize() == 0;
1317 //STREAM_SEEK_TO_END in some of the Seek backends is special cased to be
1318 //efficient, in others e.g. SotStorageStream it's really horribly slow, and in
1319 //those this should be overridden
1320 sal_uInt64
SvStream::remainingSize()
1322 sal_uInt64
const nCurr
= Tell();
1323 sal_uInt64
const nEnd
= TellEnd();
1324 sal_uInt64 nMaxAvailable
= nEnd
> nCurr
? (nEnd
-nCurr
) : 0;
1325 return nMaxAvailable
;
1328 sal_uInt64
SvStream::TellEnd()
1331 sal_uInt64
const nCurr
= Tell();
1332 sal_uInt64
const nEnd
= Seek(STREAM_SEEK_TO_END
);
1337 void SvStream::Flush()
1344 void SvStream::RefreshBuffer()
1347 SeekPos(m_nBufFilePos
);
1348 m_nBufActualLen
= static_cast<sal_uInt16
>(GetData( m_pRWBuf
.get(), m_nBufSize
));
1349 if (m_nBufActualLen
&& m_nError
== ERRCODE_IO_PENDING
)
1350 m_nError
= ERRCODE_NONE
;
1352 EncryptBuffer(m_pRWBuf
.get(), static_cast<std::size_t>(m_nBufActualLen
));
1353 m_isIoRead
= m_isIoWrite
= false;
1356 #define CRYPT_BUFSIZE 1024
1358 /// Encrypt and write
1359 std::size_t SvStream::CryptAndWriteBuffer( const void* pStart
, std::size_t nLen
)
1361 unsigned char pTemp
[CRYPT_BUFSIZE
];
1362 unsigned char const * pDataPtr
= static_cast<unsigned char const *>(pStart
);
1363 std::size_t nCount
= 0;
1364 std::size_t nBufCount
;
1365 unsigned char nMask
= m_nCryptMask
;
1368 if( nLen
>= CRYPT_BUFSIZE
)
1369 nBufCount
= CRYPT_BUFSIZE
;
1373 memcpy( pTemp
, pDataPtr
, static_cast<sal_uInt16
>(nBufCount
) );
1374 // ******** Encrypt ********
1375 for (unsigned char & rn
: pTemp
)
1377 unsigned char aCh
= rn
;
1382 // *************************
1383 nCount
+= PutData( pTemp
, nBufCount
);
1384 pDataPtr
+= nBufCount
;
1390 void SvStream::EncryptBuffer(void* pStart
, std::size_t nLen
) const
1392 unsigned char* pTemp
= static_cast<unsigned char*>(pStart
);
1393 unsigned char nMask
= m_nCryptMask
;
1395 for ( std::size_t n
=0; n
< nLen
; n
++, pTemp
++ )
1397 unsigned char aCh
= *pTemp
;
1404 static unsigned char implGetCryptMask(const char* pStr
, sal_Int32 nLen
, tools::Long nVersion
)
1406 unsigned char nCryptMask
= 0;
1411 if( nVersion
<= SOFFICE_FILEFORMAT_31
)
1415 nCryptMask
^= *pStr
;
1420 else // BugFix #25888#
1422 for( sal_Int32 i
= 0; i
< nLen
; i
++ ) {
1423 nCryptMask
^= pStr
[i
];
1424 if( nCryptMask
& 0x80 ) {
1439 void SvStream::SetCryptMaskKey(const OString
& rCryptMaskKey
)
1441 m_aCryptMaskKey
= rCryptMaskKey
;
1442 m_nCryptMask
= implGetCryptMask(m_aCryptMaskKey
.getStr(),
1443 m_aCryptMaskKey
.getLength(), GetVersion());
1446 bool SvStream::SetStreamSize(sal_uInt64
const nSize
)
1449 sal_uInt64 nFPos
= Tell();
1451 sal_uInt16 nBuf
= m_nBufSize
;
1454 if (nSize
< m_nBufFilePos
)
1456 m_nBufFilePos
= nSize
;
1458 SetBufferSize( nBuf
);
1460 DBG_ASSERT(Tell()==nFPos
,"SetStreamSize failed");
1462 return (m_nError
== ERRCODE_NONE
);
1465 SvStream
& endl( SvStream
& rStr
)
1467 LineEnd eDelim
= rStr
.GetLineDelimiter();
1468 if ( eDelim
== LINEEND_CR
)
1469 rStr
.WriteChar('\r');
1470 else if( eDelim
== LINEEND_LF
)
1471 rStr
.WriteChar('\n');
1473 rStr
.WriteChar('\r').WriteChar('\n');
1477 SvStream
& endlu( SvStream
& rStrm
)
1479 switch ( rStrm
.GetLineDelimiter() )
1482 rStrm
.WriteUnicode('\r');
1485 rStrm
.WriteUnicode('\n');
1488 rStrm
.WriteUnicode('\r').WriteUnicode('\n');
1493 SvStream
& endlub( SvStream
& rStrm
)
1495 if ( rStrm
.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE
)
1496 return endlu( rStrm
);
1498 return endl( rStrm
);
1501 SvMemoryStream::SvMemoryStream( void* pBuffer
, std::size_t bufSize
,
1504 if( eMode
& StreamMode::WRITE
)
1505 m_isWritable
= true;
1507 m_isWritable
= false;
1508 nEndOfData
= bufSize
;
1510 pBuf
= static_cast<sal_uInt8
*>(pBuffer
);
1517 SvMemoryStream::SvMemoryStream( std::size_t nInitSize
, std::size_t nResizeOffset
)
1519 m_isWritable
= true;
1522 nResize
= nResizeOffset
;
1525 if( nResize
!= 0 && nResize
< 16 )
1528 AllocateMemory( nInitSize
);
1530 SetBufferSize( 64 );
1533 SvMemoryStream::~SvMemoryStream()
1544 void SvMemoryStream::SetBuffer( void* pNewBuf
, std::size_t nCount
,
1547 SetBufferSize( 0 ); // Init buffering in the base class
1549 if( bOwnsData
&& pNewBuf
!= pBuf
)
1552 pBuf
= static_cast<sal_uInt8
*>(pNewBuf
);
1565 std::size_t SvMemoryStream::GetData( void* pData
, std::size_t nCount
)
1567 std::size_t nMaxCount
= nEndOfData
-nPos
;
1568 if( nCount
> nMaxCount
)
1572 memcpy( pData
, pBuf
+nPos
, nCount
);
1578 std::size_t SvMemoryStream::PutData( const void* pData
, std::size_t nCount
)
1583 std::size_t nMaxCount
= nSize
-nPos
;
1585 // check for overflow
1586 if( nCount
> nMaxCount
)
1590 // copy as much as possible
1592 SetError( SVSTREAM_OUTOFMEMORY
);
1596 tools::Long nNewResize
;
1597 if( nSize
&& nSize
> nResize
)
1600 nNewResize
= nResize
;
1602 if( (nCount
-nMaxCount
) < nResize
)
1604 // lacking memory is smaller than nResize,
1605 // resize accordingly
1606 if( !ReAllocateMemory( nNewResize
) )
1609 SetError( SVSTREAM_WRITE_ERROR
);
1614 // lacking memory is larger than nResize,
1615 // resize by (nCount-nMaxCount) + resize offset
1616 if( !ReAllocateMemory( nCount
-nMaxCount
+nNewResize
) )
1619 SetError( SVSTREAM_WRITE_ERROR
);
1624 assert(pBuf
&& "Possibly Reallocate failed");
1625 memcpy( pBuf
+nPos
, pData
, nCount
);
1628 if( nPos
> nEndOfData
)
1633 sal_uInt64
SvMemoryStream::SeekPos(sal_uInt64
const nNewPos
)
1635 // nEndOfData: First position in stream not allowed to read from
1636 // nSize: Size of allocated buffer
1638 // check if a truncated STREAM_SEEK_TO_END was passed
1639 assert(nNewPos
!= SAL_MAX_UINT32
);
1640 if( nNewPos
< nEndOfData
)
1642 else if( nNewPos
== STREAM_SEEK_TO_END
)
1646 if( nNewPos
>= nSize
) // Does buffer need extension?
1648 if( nResize
) // Is extension possible?
1650 tools::Long nDiff
= static_cast<tools::Long
>(nNewPos
- nSize
+ 1);
1651 nDiff
+= static_cast<tools::Long
>(nResize
);
1652 ReAllocateMemory( nDiff
);
1654 nEndOfData
= nNewPos
;
1656 else // Extension not possible, set pos to end of data
1658 // SetError( SVSTREAM_OUTOFMEMORY );
1662 else // Expand buffer size
1665 nEndOfData
= nNewPos
;
1671 void SvMemoryStream::FlushData()
1675 void SvMemoryStream::ResetError()
1677 SvStream::ClearError();
1680 void SvMemoryStream::AllocateMemory( std::size_t nNewSize
)
1682 pBuf
= new sal_uInt8
[nNewSize
];
1685 // (using Bozo algorithm)
1686 bool SvMemoryStream::ReAllocateMemory( tools::Long nDiff
)
1688 if (!m_isWritable
|| !bOwnsData
)
1691 bool bRetVal
= false;
1692 tools::Long nTemp
= static_cast<tools::Long
>(nSize
);
1694 std::size_t nNewSize
= static_cast<std::size_t>(nTemp
);
1698 sal_uInt8
* pNewBuf
= new sal_uInt8
[nNewSize
];
1700 bRetVal
= true; // Success!
1701 if( nNewSize
< nSize
) // Are we shrinking?
1703 memcpy( pNewBuf
, pBuf
, nNewSize
);
1704 if( nPos
> nNewSize
)
1706 if( nEndOfData
>= nNewSize
)
1707 nEndOfData
= nNewSize
-1;
1713 memcpy( pNewBuf
, pBuf
, nSize
);
1715 memset(pNewBuf
+ nSize
, 0x00, nNewSize
- nSize
);
1736 void SvMemoryStream::FreeMemory()
1746 void* SvMemoryStream::SwitchBuffer()
1751 Seek( STREAM_SEEK_TO_BEGIN
);
1753 void* pRetVal
= pBuf
;
1761 std::size_t nInitSize
= 512;
1762 AllocateMemory(nInitSize
);
1765 SetBufferSize( 64 );
1769 void SvMemoryStream::SetSize(sal_uInt64
const nNewSize
)
1773 SetError(SVSTREAM_INVALID_HANDLE
);
1777 tools::Long nDiff
= static_cast<tools::Long
>(nNewSize
) - static_cast<tools::Long
>(nSize
);
1778 ReAllocateMemory( nDiff
);
1781 void SvMemoryStream::MakeReadOnly()
1784 m_isWritable
= false;
1789 // Create an OString of nLen bytes from rStream
1790 // coverity[ +taint_sanitize ]
1791 OString
read_uInt8s_ToOString(SvStream
& rStrm
, std::size_t nLen
)
1793 rtl_String
*pStr
= nullptr;
1796 nLen
= std::min
<std::size_t>(nLen
, SAL_MAX_INT32
);
1797 //limit allocation to size of file, but + 1 to set eof state
1798 nLen
= std::min
<sal_uInt64
>(nLen
, rStrm
.remainingSize() + 1);
1799 //alloc a (ref-count 1) rtl_String of the desired length.
1800 //rtl_String's buffer is uninitialized, except for null termination
1801 pStr
= rtl_string_alloc(sal::static_int_cast
<sal_Int32
>(nLen
));
1802 SAL_WARN_IF(!pStr
, "tools.stream", "allocation failed");
1805 std::size_t nWasRead
= rStrm
.ReadBytes(pStr
->buffer
, nLen
);
1806 if (nWasRead
!= nLen
)
1808 //on (typically unlikely) short read set length to what we could
1809 //read, and null terminate. Excess buffer capacity remains of
1810 //course, could create a (true) replacement OString if it matters.
1811 pStr
->length
= sal::static_int_cast
<sal_Int32
>(nWasRead
);
1812 pStr
->buffer
[pStr
->length
] = 0;
1817 //take ownership of buffer and return, otherwise return empty string
1818 return pStr
? OString(pStr
, SAL_NO_ACQUIRE
) : OString();
1821 // Create an OUString of nLen sal_Unicode code units from rStream
1822 // coverity[ +taint_sanitize ]
1823 OUString
read_uInt16s_ToOUString(SvStream
& rStrm
, std::size_t nLen
)
1825 rtl_uString
*pStr
= nullptr;
1828 nLen
= std::min
<std::size_t>(nLen
, SAL_MAX_INT32
);
1829 //limit allocation to size of file, but + 1 to set eof state
1830 nLen
= o3tl::sanitizing_min
<sal_uInt64
>(nLen
, (rStrm
.remainingSize() + 2) / 2);
1831 //alloc a (ref-count 1) rtl_uString of the desired length.
1832 //rtl_String's buffer is uninitialized, except for null termination
1833 pStr
= rtl_uString_alloc(sal::static_int_cast
<sal_Int32
>(nLen
));
1834 SAL_WARN_IF(!pStr
, "tools.stream", "allocation failed");
1837 std::size_t nWasRead
= rStrm
.ReadBytes(pStr
->buffer
, nLen
*2)/2;
1838 if (nWasRead
!= nLen
)
1840 //on (typically unlikely) short read set length to what we could
1841 //read, and null terminate. Excess buffer capacity remains of
1842 //course, could create a (true) replacement OUString if it matters.
1843 pStr
->length
= sal::static_int_cast
<sal_Int32
>(nWasRead
);
1844 pStr
->buffer
[pStr
->length
] = 0;
1846 if (rStrm
.IsEndianSwap())
1848 for (sal_Int32 i
= 0; i
< pStr
->length
; ++i
)
1849 pStr
->buffer
[i
] = OSL_SWAPWORD(pStr
->buffer
[i
]);
1854 // take ownership of buffer and return, otherwise return empty string
1855 // coverity[tainted_data] - unhelpful untrusted loop bound
1856 return pStr
? OUString(pStr
, SAL_NO_ACQUIRE
) : OUString();
1861 template <typename T
, typename O
> T
tmpl_convertLineEnd(const T
&rIn
, LineEnd eLineEnd
)
1863 // Determine linebreaks and compute length
1864 bool bConvert
= false; // Needs conversion
1865 sal_Int32 nStrLen
= rIn
.getLength();
1866 sal_Int32 nLineEndLen
= (eLineEnd
== LINEEND_CRLF
) ? 2 : 1;
1867 sal_Int32 nLen
= 0; // Target length
1868 sal_Int32 i
= 0; // Source counter
1872 // \r or \n causes linebreak
1873 if ( (rIn
[i
] == '\r') || (rIn
[i
] == '\n') )
1875 nLen
= nLen
+ nLineEndLen
;
1877 // If set already, skip expensive test
1880 // Do we need to convert?
1881 if ( ((eLineEnd
!= LINEEND_LF
) && (rIn
[i
] == '\n')) ||
1882 ((eLineEnd
== LINEEND_CRLF
) && (i
+1) < nStrLen
&& (rIn
[i
+1] != '\n')) ||
1883 ((eLineEnd
== LINEEND_LF
) &&
1884 ((rIn
[i
] == '\r') || ((i
+1) < nStrLen
&& rIn
[i
+1] == '\r'))) ||
1885 ((eLineEnd
== LINEEND_CR
) &&
1886 ((rIn
[i
] == '\n') || ((i
+1) < nStrLen
&& rIn
[i
+1] == '\n'))) )
1890 // skip char if \r\n or \n\r
1891 if ( (i
+1) < nStrLen
&& ((rIn
[i
+1] == '\r') || (rIn
[i
+1] == '\n')) &&
1892 (rIn
[i
] != rIn
[i
+1]) )
1903 // convert linebreaks, insert string
1908 // \r or \n causes linebreak
1909 if ( (rIn
[i
] == '\r') || (rIn
[i
] == '\n') )
1911 if ( eLineEnd
== LINEEND_CRLF
)
1913 aNewData
.append('\r');
1914 aNewData
.append('\n');
1918 if ( eLineEnd
== LINEEND_CR
)
1919 aNewData
.append('\r');
1921 aNewData
.append('\n');
1924 if ( (i
+1) < nStrLen
&& ((rIn
[i
+1] == '\r') || (rIn
[i
+1] == '\n')) &&
1925 (rIn
[i
] != rIn
[i
+1]) )
1930 aNewData
.append(rIn
[i
]);
1936 return aNewData
.makeStringAndClear();
1940 OString
convertLineEnd(const OString
&rIn
, LineEnd eLineEnd
)
1942 return tmpl_convertLineEnd
<OString
, OStringBuffer
>(rIn
, eLineEnd
);
1945 OUString
convertLineEnd(const OUString
&rIn
, LineEnd eLineEnd
)
1947 return tmpl_convertLineEnd
<OUString
, OUStringBuffer
>(rIn
, eLineEnd
);
1950 std::size_t write_uInt32_lenPrefixed_uInt16s_FromOUString(SvStream
& rStrm
,
1951 std::u16string_view rStr
)
1953 std::size_t nWritten
= 0;
1954 sal_uInt32 nUnits
= std::min
<std::size_t>(rStr
.size(), std::numeric_limits
<sal_uInt32
>::max());
1955 SAL_WARN_IF(static_cast<std::size_t>(nUnits
) != static_cast<std::size_t>(rStr
.size()),
1957 "string too long for prefix count to fit in output type");
1958 rStrm
.WriteUInt32(nUnits
);
1961 nWritten
+= sizeof(sal_uInt32
);
1962 nWritten
+= write_uInt16s_FromOUString(rStrm
, rStr
, nUnits
);
1967 std::size_t write_uInt16_lenPrefixed_uInt16s_FromOUString(SvStream
& rStrm
,
1968 std::u16string_view rStr
)
1970 std::size_t nWritten
= 0;
1971 sal_uInt16 nUnits
= std::min
<std::size_t>(rStr
.size(), std::numeric_limits
<sal_uInt16
>::max());
1972 SAL_WARN_IF(nUnits
!= rStr
.size(),
1974 "string too long for prefix count to fit in output type");
1975 rStrm
.WriteUInt16(nUnits
);
1978 nWritten
+= sizeof(nUnits
);
1979 nWritten
+= write_uInt16s_FromOUString(rStrm
, rStr
, nUnits
);
1984 std::size_t write_uInt16_lenPrefixed_uInt8s_FromOString(SvStream
& rStrm
,
1985 std::string_view rStr
)
1987 std::size_t nWritten
= 0;
1988 sal_uInt16 nUnits
= std::min
<std::size_t>(rStr
.size(), std::numeric_limits
<sal_uInt16
>::max());
1989 SAL_WARN_IF(static_cast<std::size_t>(nUnits
) != static_cast<std::size_t>(rStr
.size()),
1991 "string too long for sal_uInt16 count to fit in output type");
1992 rStrm
.WriteUInt16( nUnits
);
1995 nWritten
+= sizeof(sal_uInt16
);
1996 nWritten
+= write_uInt8s_FromOString(rStrm
, rStr
, nUnits
);
2001 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */