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>
31 #include <o3tl/safeint.hxx>
32 #include <osl/endian.h>
33 #include <osl/diagnose.h>
34 #include <rtl/strbuf.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
)
364 m_nEndian
= nNewFormat
;
367 if (m_nEndian
== SvStreamEndian::LITTLE
)
370 if (m_nEndian
== SvStreamEndian::BIG
)
375 void SvStream::SetBufferSize( sal_uInt16 nBufferSize
)
377 sal_uInt64
const nActualFilePos
= Tell();
378 bool bDontSeek
= (m_pRWBuf
== nullptr);
380 if (m_isDirty
&& m_isWritable
) // due to Windows NT: Access denied
386 m_nBufFilePos
+= m_nBufActualPos
;
392 m_nBufSize
= nBufferSize
;
394 m_pRWBuf
.reset(new sal_uInt8
[ m_nBufSize
]);
395 m_pBufPos
= m_pRWBuf
.get();
396 m_isIoRead
= m_isIoWrite
= false;
398 SeekPos( nActualFilePos
);
401 void SvStream::ClearBuffer()
406 m_pBufPos
= m_pRWBuf
.get();
408 m_isIoRead
= m_isIoWrite
= false;
413 void SvStream::ResetError()
418 bool SvStream::ReadByteStringLine( OUString
& rStr
, rtl_TextEncoding eSrcCharSet
,
419 sal_Int32 nMaxBytesToRead
)
422 bool bRet
= ReadLine( aStr
, nMaxBytesToRead
);
423 rStr
= OStringToOUString(aStr
, eSrcCharSet
);
427 bool SvStream::ReadLine( OString
& rStr
, sal_Int32 nMaxBytesToRead
)
431 sal_uInt64 nOldFilePos
= Tell();
433 std::size_t nTotalLen
= 0;
435 OStringBuffer
aBuf(4096);
436 while( !bEnd
&& !GetError() ) // Don't test for EOF as we
437 // are reading block-wise!
439 sal_uInt16 nLen
= static_cast<sal_uInt16
>(ReadBytes(buf
, sizeof(buf
)-1));
442 if ( aBuf
.isEmpty() )
444 // Exit on first block-read error
454 for( j
= n
= 0; j
< nLen
; ++j
)
457 if ( c
== '\n' || c
== '\r' )
467 if (nTotalLen
> o3tl::make_unsigned(nMaxBytesToRead
))
469 n
-= nTotalLen
- nMaxBytesToRead
;
470 nTotalLen
= nMaxBytesToRead
;
477 if ( !bEnd
&& !GetError() && !aBuf
.isEmpty() )
480 nOldFilePos
+= nTotalLen
;
481 if( Tell() > nOldFilePos
)
483 Seek( nOldFilePos
); // Seek pointer due to BlockRead above
485 if ( bEnd
&& (c
=='\r' || c
=='\n') ) // Special treatment for DOS files
488 std::size_t nLen
= ReadBytes(&cTemp
, sizeof(cTemp
));
490 if( cTemp
== c
|| (cTemp
!= '\n' && cTemp
!= '\r') )
497 rStr
= aBuf
.makeStringAndClear();
501 bool SvStream::ReadUniStringLine( OUString
& rStr
, sal_Int32 nMaxCodepointsToRead
)
503 sal_Unicode buf
[256+1];
505 sal_uInt64 nOldFilePos
= Tell();
507 std::size_t nTotalLen
= 0;
509 DBG_ASSERT( sizeof(sal_Unicode
) == sizeof(sal_uInt16
), "ReadUniStringLine: swapping sizeof(sal_Unicode) not implemented" );
511 OUStringBuffer
aBuf(4096);
512 while( !bEnd
&& !GetError() ) // Don't test for EOF as we
513 // are reading block-wise!
515 sal_uInt16 nLen
= static_cast<sal_uInt16
>(ReadBytes( buf
, sizeof(buf
)-sizeof(sal_Unicode
)));
516 nLen
/= sizeof(sal_Unicode
);
519 if ( aBuf
.isEmpty() )
521 // exit on first BlockRead error
531 for( j
= n
= 0; j
< nLen
; ++j
)
534 SwapNumber( buf
[n
] );
536 if ( c
== '\n' || c
== '\r' )
541 // erAck 26.02.01: Old behavior was no special treatment of '\0'
542 // character here, but a following rStr+=c did ignore it. Is this
543 // really intended? Or should a '\0' better terminate a line?
544 // The nOldFilePos stuff wasn't correct then anyways.
553 if (nTotalLen
> o3tl::make_unsigned(nMaxCodepointsToRead
))
555 n
-= nTotalLen
- nMaxCodepointsToRead
;
556 nTotalLen
= nMaxCodepointsToRead
;
560 aBuf
.append( buf
, n
);
563 if ( !bEnd
&& !GetError() && !aBuf
.isEmpty() )
566 nOldFilePos
+= nTotalLen
* sizeof(sal_Unicode
);
567 if( Tell() > nOldFilePos
)
568 nOldFilePos
+= sizeof(sal_Unicode
);
569 Seek( nOldFilePos
); // seek due to BlockRead above
571 if ( bEnd
&& (c
=='\r' || c
=='\n') ) // special treatment for DOS files
574 ReadBytes( &cTemp
, sizeof(cTemp
) );
577 if( cTemp
== c
|| (cTemp
!= '\n' && cTemp
!= '\r') )
583 rStr
= aBuf
.makeStringAndClear();
587 bool SvStream::ReadUniOrByteStringLine( OUString
& rStr
, rtl_TextEncoding eSrcCharSet
,
588 sal_Int32 nMaxCodepointsToRead
)
590 if ( eSrcCharSet
== RTL_TEXTENCODING_UNICODE
)
591 return ReadUniStringLine( rStr
, nMaxCodepointsToRead
);
593 return ReadByteStringLine( rStr
, eSrcCharSet
, nMaxCodepointsToRead
);
596 OString
read_zeroTerminated_uInt8s_ToOString(SvStream
& rStream
)
598 OStringBuffer
aOutput(256);
602 sal_uInt64 nFilePos
= rStream
.Tell();
604 while( !bEnd
&& !rStream
.GetError() )
606 std::size_t nLen
= rStream
.ReadBytes(buf
, sizeof(buf
)-1);
610 std::size_t nReallyRead
= nLen
;
611 const char* pPtr
= buf
;
612 while (nLen
&& *pPtr
)
618 bEnd
= ( nReallyRead
< sizeof(buf
)-1 ) // read less than attempted to read
619 || ( ( nLen
> 0 ) // OR it is inside the block we read
620 && ( 0 == *pPtr
) // AND found a string terminator
623 aOutput
.append(buf
, pPtr
- buf
);
626 nFilePos
+= aOutput
.getLength();
627 if (rStream
.Tell() > nFilePos
)
628 rStream
.Seek(nFilePos
+1); // seek due to FileRead above
629 return aOutput
.makeStringAndClear();
632 OUString
read_zeroTerminated_uInt8s_ToOUString(SvStream
& rStream
, rtl_TextEncoding eEnc
)
634 return OStringToOUString(
635 read_zeroTerminated_uInt8s_ToOString(rStream
), eEnc
);
638 /** Attempt to write a prefixed sequence of nUnits 16bit units from an OUString,
639 returned value is number of bytes written */
640 std::size_t write_uInt16s_FromOUString(SvStream
& rStrm
, std::u16string_view rStr
,
643 DBG_ASSERT( sizeof(sal_Unicode
) == sizeof(sal_uInt16
), "write_uInt16s_FromOUString: swapping sizeof(sal_Unicode) not implemented" );
644 std::size_t nWritten
;
645 if (!rStrm
.IsEndianSwap())
646 nWritten
= rStrm
.WriteBytes(rStr
.data(), nUnits
* sizeof(sal_Unicode
));
649 std::size_t nLen
= nUnits
;
650 sal_Unicode aBuf
[384];
651 sal_Unicode
* const pTmp
= ( nLen
> 384 ? new sal_Unicode
[nLen
] : aBuf
);
652 memcpy( pTmp
, rStr
.data(), nLen
* sizeof(sal_Unicode
) );
653 sal_Unicode
* p
= pTmp
;
654 const sal_Unicode
* const pStop
= pTmp
+ nLen
;
660 nWritten
= rStrm
.WriteBytes( pTmp
, nLen
* sizeof(sal_Unicode
) );
667 bool SvStream::WriteUnicodeOrByteText( std::u16string_view rStr
, rtl_TextEncoding eDestCharSet
)
669 if ( eDestCharSet
== RTL_TEXTENCODING_UNICODE
)
671 write_uInt16s_FromOUString(*this, rStr
, rStr
.size());
672 return m_nError
== ERRCODE_NONE
;
676 OString
aStr(OUStringToOString(rStr
, eDestCharSet
));
677 write_uInt8s_FromOString(*this, aStr
, aStr
.getLength());
678 return m_nError
== ERRCODE_NONE
;
682 bool SvStream::WriteByteStringLine( std::u16string_view rStr
, rtl_TextEncoding eDestCharSet
)
684 return WriteLine(OUStringToOString(rStr
, eDestCharSet
));
687 bool SvStream::WriteLine(std::string_view rStr
)
689 WriteBytes(rStr
.data(), rStr
.size());
691 return m_nError
== ERRCODE_NONE
;
694 bool SvStream::WriteUniOrByteChar( sal_Unicode ch
, rtl_TextEncoding eDestCharSet
)
696 if ( eDestCharSet
== RTL_TEXTENCODING_UNICODE
)
700 OString
aStr(&ch
, 1, eDestCharSet
);
701 WriteBytes(aStr
.getStr(), aStr
.getLength());
703 return m_nError
== ERRCODE_NONE
;
706 void SvStream::StartWritingUnicodeText()
708 // BOM, Byte Order Mark, U+FEFF, see
709 // http://www.unicode.org/faq/utf_bom.html#BOM
710 // Upon read: 0xfeff(-257) => no swap; 0xfffe(-2) => swap
711 writeNumberWithoutSwap(sal_uInt16(0xfeff)); // write native format
714 void SvStream::StartReadingUnicodeText( rtl_TextEncoding eReadBomCharSet
)
716 if (!( eReadBomCharSet
== RTL_TEXTENCODING_DONTKNOW
||
717 eReadBomCharSet
== RTL_TEXTENCODING_UNICODE
||
718 eReadBomCharSet
== RTL_TEXTENCODING_UTF8
))
719 return; // nothing to read
721 bool bTryUtf8
= false;
723 sal_sSize nBack
= sizeof(nFlag
);
729 if ( eReadBomCharSet
== RTL_TEXTENCODING_DONTKNOW
||
730 eReadBomCharSet
== RTL_TEXTENCODING_UNICODE
)
735 if ( eReadBomCharSet
== RTL_TEXTENCODING_DONTKNOW
||
736 eReadBomCharSet
== RTL_TEXTENCODING_UNICODE
)
738 SetEndian( m_nEndian
== SvStreamEndian::BIG
? SvStreamEndian::LITTLE
: SvStreamEndian::BIG
);
743 if (m_nEndian
== SvStreamEndian::BIG
&&
744 (eReadBomCharSet
== RTL_TEXTENCODING_DONTKNOW
||
745 eReadBomCharSet
== RTL_TEXTENCODING_UTF8
))
749 if (m_nEndian
== SvStreamEndian::LITTLE
&&
750 (eReadBomCharSet
== RTL_TEXTENCODING_DONTKNOW
||
751 eReadBomCharSet
== RTL_TEXTENCODING_UTF8
))
759 unsigned char nChar(0);
760 nBack
+= sizeof(nChar
);
763 nBack
= 0; // it is UTF-8
766 SeekRel( -nBack
); // no BOM, pure data
769 sal_uInt64
SvStream::SeekRel(sal_Int64
const nPos
)
771 sal_uInt64 nActualPos
= Tell();
775 if (SAL_MAX_UINT64
- nActualPos
> o3tl::make_unsigned(nPos
))
780 sal_uInt64
const nAbsPos
= static_cast<sal_uInt64
>(-nPos
);
781 if ( nActualPos
>= nAbsPos
)
782 nActualPos
-= nAbsPos
;
785 assert((m_pBufPos
!= nullptr) == bool(m_pRWBuf
));
788 m_pBufPos
= m_pRWBuf
.get() + nActualPos
;
790 return Seek( nActualPos
);
793 template <typename T
> SvStream
& SvStream::ReadNumber(T
& r
)
796 readNumberWithoutSwap(n
);
806 SvStream
& SvStream::ReadUInt16(sal_uInt16
& r
) { return ReadNumber(r
); }
807 SvStream
& SvStream::ReadUInt32(sal_uInt32
& r
) { return ReadNumber(r
); }
808 SvStream
& SvStream::ReadUInt64(sal_uInt64
& r
) { return ReadNumber(r
); }
809 SvStream
& SvStream::ReadInt16(sal_Int16
& r
) { return ReadNumber(r
); }
810 SvStream
& SvStream::ReadInt32(sal_Int32
& r
) { return ReadNumber(r
); }
811 SvStream
& SvStream::ReadInt64(sal_Int64
& r
) { return ReadNumber(r
); }
813 SvStream
& SvStream::ReadSChar( signed char& r
)
815 if (m_isIoRead
&& sizeof(signed char) <= m_nBufFree
)
818 m_nBufActualPos
+= sizeof(signed char);
819 m_pBufPos
+= sizeof(signed char);
820 m_nBufFree
-= sizeof(signed char);
823 ReadBytes( &r
, sizeof(signed char) );
827 // Special treatment for Chars due to PutBack
829 SvStream
& SvStream::ReadChar( char& r
)
831 if (m_isIoRead
&& sizeof(char) <= m_nBufFree
)
834 m_nBufActualPos
+= sizeof(char);
835 m_pBufPos
+= sizeof(char);
836 m_nBufFree
-= sizeof(char);
839 ReadBytes( &r
, sizeof(char) );
843 SvStream
& SvStream::ReadUChar( unsigned char& r
)
845 if (m_isIoRead
&& sizeof(char) <= m_nBufFree
)
848 m_nBufActualPos
+= sizeof(char);
849 m_pBufPos
+= sizeof(char);
850 m_nBufFree
-= sizeof(char);
853 ReadBytes( &r
, sizeof(char) );
857 SvStream
& SvStream::ReadUtf16(sal_Unicode
& r
) { return ReadNumber(r
); }
859 SvStream
& SvStream::ReadCharAsBool( bool& r
)
861 if (m_isIoRead
&& sizeof(char) <= m_nBufFree
)
864 *m_pBufPos
> 1, "tools.stream", unsigned(*m_pBufPos
) << " not 0/1");
866 m_nBufActualPos
+= sizeof(char);
867 m_pBufPos
+= sizeof(char);
868 m_nBufFree
-= sizeof(char);
873 if (ReadBytes(&c
, 1) == 1)
875 SAL_WARN_IF(c
> 1, "tools.stream", unsigned(c
) << " not 0/1");
882 SvStream
& SvStream::ReadFloat(float& r
)
885 readNumberWithoutSwap(n
);
897 SvStream
& SvStream::ReadDouble(double& r
)
900 readNumberWithoutSwap(n
);
912 SvStream
& SvStream::ReadStream( SvStream
& rStream
)
914 const sal_uInt32 cBufLen
= 0x8000;
915 std::unique_ptr
<char[]> pBuf( new char[ cBufLen
] );
919 nCount
= ReadBytes( pBuf
.get(), cBufLen
);
920 rStream
.WriteBytes( pBuf
.get(), nCount
);
921 } while( nCount
== cBufLen
);
926 template <typename T
> SvStream
& SvStream::WriteNumber(T n
)
930 writeNumberWithoutSwap(n
);
934 SvStream
& SvStream::WriteUInt16(sal_uInt16 v
) { return WriteNumber(v
); }
935 SvStream
& SvStream::WriteUInt32(sal_uInt32 v
) { return WriteNumber(v
); }
936 SvStream
& SvStream::WriteUInt64(sal_uInt64 v
) { return WriteNumber(v
); }
937 SvStream
& SvStream::WriteInt16(sal_Int16 v
) { return WriteNumber(v
); }
938 SvStream
& SvStream::WriteInt32(sal_Int32 v
) { return WriteNumber(v
); }
939 SvStream
& SvStream::WriteInt64(sal_Int64 v
) { return WriteNumber(v
); }
941 SvStream
& SvStream::WriteSChar( signed char v
)
944 if (m_isIoWrite
&& sizeof(signed char) <= m_nBufFree
)
947 m_pBufPos
++; // sizeof(char);
949 if (m_nBufActualPos
> m_nBufActualLen
) // Append ?
950 m_nBufActualLen
= m_nBufActualPos
;
951 m_nBufFree
--; // = sizeof(char);
955 WriteBytes( &v
, sizeof(signed char) );
959 // Special treatment for Chars due to PutBack
961 SvStream
& SvStream::WriteChar( char v
)
964 if (m_isIoWrite
&& sizeof(char) <= m_nBufFree
)
967 m_pBufPos
++; // sizeof(char);
969 if (m_nBufActualPos
> m_nBufActualLen
) // Append ?
970 m_nBufActualLen
= m_nBufActualPos
;
971 m_nBufFree
--; // = sizeof(char);
975 WriteBytes( &v
, sizeof(char) );
979 SvStream
& SvStream::WriteUChar( unsigned char v
)
982 if (m_isIoWrite
&& sizeof(char) <= m_nBufFree
)
984 *reinterpret_cast<unsigned char*>(m_pBufPos
) = v
;
985 m_pBufPos
++; // = sizeof(char);
986 m_nBufActualPos
++; // = sizeof(char);
987 if (m_nBufActualPos
> m_nBufActualLen
) // Append ?
988 m_nBufActualLen
= m_nBufActualPos
;
993 WriteBytes( &v
, sizeof(char) );
997 SvStream
& SvStream::WriteUInt8( sal_uInt8 v
)
999 return WriteUChar(v
);
1002 SvStream
& SvStream::WriteUnicode( sal_Unicode v
)
1004 return WriteUInt16(v
);
1007 SvStream
& SvStream::WriteFloat( float v
)
1013 writeNumberWithoutSwap(v
);
1017 SvStream
& SvStream::WriteDouble ( const double& r
)
1024 writeNumberWithoutSwap(nHelp
);
1030 writeNumberWithoutSwap(r
);
1035 SvStream
& SvStream::WriteCharPtr( const char* pBuf
)
1037 WriteBytes( pBuf
, strlen(pBuf
) );
1041 SvStream
& SvStream::WriteStream( SvStream
& rStream
)
1043 const sal_uInt32 cBufLen
= 0x8000;
1044 std::unique_ptr
<char[]> pBuf( new char[ cBufLen
] );
1047 nCount
= rStream
.ReadBytes( pBuf
.get(), cBufLen
);
1048 WriteBytes( pBuf
.get(), nCount
);
1049 } while( nCount
== cBufLen
);
1054 sal_uInt64
SvStream::WriteStream( SvStream
& rStream
, sal_uInt64 nSize
)
1056 const sal_uInt32 cBufLen
= 0x8000;
1057 std::unique_ptr
<char[]> pBuf( new char[ cBufLen
] );
1058 sal_uInt32 nCurBufLen
= cBufLen
;
1060 sal_uInt64 nWriteSize
= nSize
;
1064 nCurBufLen
= std::min
<sal_uInt64
>(nCurBufLen
, nWriteSize
);
1065 nCount
= rStream
.ReadBytes(pBuf
.get(), nCurBufLen
);
1066 WriteBytes( pBuf
.get(), nCount
);
1067 nWriteSize
-= nCount
;
1069 while( nWriteSize
&& nCount
== nCurBufLen
);
1071 return nSize
- nWriteSize
;
1074 OUString
SvStream::ReadUniOrByteString( rtl_TextEncoding eSrcCharSet
)
1076 // read UTF-16 string directly from stream ?
1077 if (eSrcCharSet
== RTL_TEXTENCODING_UNICODE
)
1078 return read_uInt32_lenPrefixed_uInt16s_ToOUString(*this);
1079 return read_uInt16_lenPrefixed_uInt8s_ToOUString(*this, eSrcCharSet
);
1082 SvStream
& SvStream::WriteUniOrByteString( std::u16string_view rStr
, rtl_TextEncoding eDestCharSet
)
1084 // write UTF-16 string directly into stream ?
1085 if (eDestCharSet
== RTL_TEXTENCODING_UNICODE
)
1086 write_uInt32_lenPrefixed_uInt16s_FromOUString(*this, rStr
);
1088 write_uInt16_lenPrefixed_uInt8s_FromOUString(*this, rStr
, eDestCharSet
);
1092 void SvStream::FlushBuffer()
1094 if (m_isDirty
) // Does stream require a flush?
1096 SeekPos(m_nBufFilePos
);
1098 CryptAndWriteBuffer(m_pRWBuf
.get(), m_nBufActualLen
);
1099 else if (PutData(m_pRWBuf
.get(), m_nBufActualLen
) != m_nBufActualLen
)
1100 SetError(SVSTREAM_WRITE_ERROR
);
1105 std::size_t SvStream::ReadBytes( void* pData
, std::size_t nCount
)
1107 std::size_t nSaveCount
= nCount
;
1111 nCount
= GetData( pData
,nCount
);
1113 EncryptBuffer(pData
, nCount
);
1114 m_nBufFilePos
+= nCount
;
1118 // check if block is completely within buffer
1120 m_isIoWrite
= false;
1121 if (nCount
<= o3tl::make_unsigned(m_nBufActualLen
- m_nBufActualPos
))
1125 memcpy(pData
, m_pBufPos
, nCount
);
1126 m_nBufActualPos
= m_nBufActualPos
+ static_cast<sal_uInt16
>(nCount
);
1127 m_pBufPos
+= nCount
;
1128 m_nBufFree
= m_nBufFree
- static_cast<sal_uInt16
>(nCount
);
1134 // Does data block fit into buffer?
1135 if (nCount
> m_nBufSize
)
1137 // => No! Thus read directly
1138 // into target area without using the buffer
1142 SeekPos(m_nBufFilePos
+ m_nBufActualPos
);
1143 m_nBufActualLen
= 0;
1144 m_pBufPos
= m_pRWBuf
.get();
1145 nCount
= GetData( pData
, nCount
);
1147 EncryptBuffer(pData
, nCount
);
1148 m_nBufFilePos
+= nCount
;
1149 m_nBufFilePos
+= m_nBufActualPos
;
1150 m_nBufActualPos
= 0;
1154 // => Yes. Fill buffer first, then copy to target area
1156 m_nBufFilePos
+= m_nBufActualPos
;
1157 SeekPos(m_nBufFilePos
);
1159 // TODO: Typecast before GetData, sal_uInt16 nCountTmp
1160 std::size_t nCountTmp
= GetData( m_pRWBuf
.get(), m_nBufSize
);
1162 EncryptBuffer(m_pRWBuf
.get(), nCountTmp
);
1163 m_nBufActualLen
= static_cast<sal_uInt16
>(nCountTmp
);
1164 if( nCount
> nCountTmp
)
1166 nCount
= nCountTmp
; // trim count back, EOF see below
1168 memcpy( pData
, m_pRWBuf
.get(), nCount
);
1169 m_nBufActualPos
= static_cast<sal_uInt16
>(nCount
);
1170 m_pBufPos
= m_pRWBuf
.get() + nCount
;
1175 m_nBufFree
= m_nBufActualLen
- m_nBufActualPos
;
1176 if (nCount
!= nSaveCount
&& m_nError
!= ERRCODE_IO_PENDING
)
1178 if (nCount
== nSaveCount
&& m_nError
== ERRCODE_IO_PENDING
)
1179 m_nError
= ERRCODE_NONE
;
1183 std::size_t SvStream::WriteBytes( const void* pData
, std::size_t nCount
)
1190 SetError( ERRCODE_IO_CANTWRITE
);
1197 nCount
= CryptAndWriteBuffer( pData
, nCount
);
1199 nCount
= PutData( pData
, nCount
);
1200 m_nBufFilePos
+= nCount
;
1206 if (nCount
<= o3tl::make_unsigned(m_nBufSize
- m_nBufActualPos
))
1208 memcpy( m_pBufPos
, pData
, nCount
);
1209 m_nBufActualPos
= m_nBufActualPos
+ static_cast<sal_uInt16
>(nCount
);
1210 // Update length if buffer was updated
1211 if (m_nBufActualPos
> m_nBufActualLen
)
1212 m_nBufActualLen
= m_nBufActualPos
;
1214 m_pBufPos
+= nCount
;
1221 // Does data block fit into buffer?
1222 if (nCount
> m_nBufSize
)
1224 m_isIoWrite
= false;
1225 m_nBufFilePos
+= m_nBufActualPos
;
1226 m_nBufActualLen
= 0;
1227 m_nBufActualPos
= 0;
1228 m_pBufPos
= m_pRWBuf
.get();
1229 SeekPos(m_nBufFilePos
);
1231 nCount
= CryptAndWriteBuffer( pData
, nCount
);
1233 nCount
= PutData( pData
, nCount
);
1234 m_nBufFilePos
+= nCount
;
1238 // Copy block to buffer
1239 memcpy( m_pRWBuf
.get(), pData
, nCount
);
1242 m_nBufFilePos
+= m_nBufActualPos
;
1243 m_nBufActualPos
= static_cast<sal_uInt16
>(nCount
);
1244 m_pBufPos
= m_pRWBuf
.get() + nCount
;
1245 m_nBufActualLen
= static_cast<sal_uInt16
>(nCount
);
1249 m_nBufFree
= m_nBufSize
- m_nBufActualPos
;
1253 sal_uInt64
SvStream::Seek(sal_uInt64
const nFilePos
)
1255 m_isIoRead
= m_isIoWrite
= false;
1259 m_nBufFilePos
= SeekPos( nFilePos
);
1260 DBG_ASSERT(Tell() == m_nBufFilePos
,"Out Of Sync!");
1261 return m_nBufFilePos
;
1264 // Is seek position within buffer?
1265 if (nFilePos
>= m_nBufFilePos
&& nFilePos
<= (m_nBufFilePos
+ m_nBufActualLen
))
1267 m_nBufActualPos
= static_cast<sal_uInt16
>(nFilePos
- m_nBufFilePos
);
1268 m_pBufPos
= m_pRWBuf
.get() + m_nBufActualPos
;
1269 // Update m_nBufFree to avoid crash upon PutBack
1270 m_nBufFree
= m_nBufActualLen
- m_nBufActualPos
;
1275 m_nBufActualLen
= 0;
1276 m_nBufActualPos
= 0;
1277 m_pBufPos
= m_pRWBuf
.get();
1278 m_nBufFilePos
= SeekPos( nFilePos
);
1280 return m_nBufFilePos
+ m_nBufActualPos
;
1283 bool checkSeek(SvStream
&rSt
, sal_uInt64 nOffset
)
1285 const sal_uInt64 nMaxSeek
= rSt
.TellEnd();
1286 return (nOffset
<= nMaxSeek
&& rSt
.Seek(nOffset
) == nOffset
);
1291 bool isEmptyFileUrl(const OUString
& rUrl
)
1293 if (!comphelper::isFileUrl(rUrl
))
1298 SvFileStream
aStream(rUrl
, StreamMode::READ
);
1299 if (!aStream
.IsOpen())
1304 return aStream
.remainingSize() == 0;
1308 //STREAM_SEEK_TO_END in some of the Seek backends is special cased to be
1309 //efficient, in others e.g. SotStorageStream it's really horribly slow, and in
1310 //those this should be overridden
1311 sal_uInt64
SvStream::remainingSize()
1313 sal_uInt64
const nCurr
= Tell();
1314 sal_uInt64
const nEnd
= TellEnd();
1315 sal_uInt64 nMaxAvailable
= nEnd
> nCurr
? (nEnd
-nCurr
) : 0;
1316 return nMaxAvailable
;
1319 sal_uInt64
SvStream::TellEnd()
1322 sal_uInt64
const nCurr
= Tell();
1323 sal_uInt64
const nEnd
= Seek(STREAM_SEEK_TO_END
);
1328 void SvStream::Flush()
1335 void SvStream::RefreshBuffer()
1338 SeekPos(m_nBufFilePos
);
1339 m_nBufActualLen
= static_cast<sal_uInt16
>(GetData( m_pRWBuf
.get(), m_nBufSize
));
1340 if (m_nBufActualLen
&& m_nError
== ERRCODE_IO_PENDING
)
1341 m_nError
= ERRCODE_NONE
;
1343 EncryptBuffer(m_pRWBuf
.get(), static_cast<std::size_t>(m_nBufActualLen
));
1344 m_isIoRead
= m_isIoWrite
= false;
1347 SvStream
& SvStream::WriteInt32AsString(sal_Int32 nInt32
)
1350 std::size_t nLen
= sprintf(buffer
, "%" SAL_PRIdINT32
, nInt32
);
1351 WriteBytes(buffer
, nLen
);
1355 SvStream
& SvStream::WriteUInt32AsString(sal_uInt32 nUInt32
)
1358 std::size_t nLen
= sprintf(buffer
, "%" SAL_PRIuUINT32
, nUInt32
);
1359 WriteBytes(buffer
, nLen
);
1363 #define CRYPT_BUFSIZE 1024
1365 /// Encrypt and write
1366 std::size_t SvStream::CryptAndWriteBuffer( const void* pStart
, std::size_t nLen
)
1368 unsigned char pTemp
[CRYPT_BUFSIZE
];
1369 unsigned char const * pDataPtr
= static_cast<unsigned char const *>(pStart
);
1370 std::size_t nCount
= 0;
1371 std::size_t nBufCount
;
1372 unsigned char nMask
= m_nCryptMask
;
1375 if( nLen
>= CRYPT_BUFSIZE
)
1376 nBufCount
= CRYPT_BUFSIZE
;
1380 memcpy( pTemp
, pDataPtr
, static_cast<sal_uInt16
>(nBufCount
) );
1381 // ******** Encrypt ********
1382 for (unsigned char & rn
: pTemp
)
1384 unsigned char aCh
= rn
;
1389 // *************************
1390 nCount
+= PutData( pTemp
, nBufCount
);
1391 pDataPtr
+= nBufCount
;
1397 void SvStream::EncryptBuffer(void* pStart
, std::size_t nLen
) const
1399 unsigned char* pTemp
= static_cast<unsigned char*>(pStart
);
1400 unsigned char nMask
= m_nCryptMask
;
1402 for ( std::size_t n
=0; n
< nLen
; n
++, pTemp
++ )
1404 unsigned char aCh
= *pTemp
;
1411 static unsigned char implGetCryptMask(const char* pStr
, sal_Int32 nLen
, tools::Long nVersion
)
1413 unsigned char nCryptMask
= 0;
1418 if( nVersion
<= SOFFICE_FILEFORMAT_31
)
1422 nCryptMask
^= *pStr
;
1427 else // BugFix #25888#
1429 for( sal_Int32 i
= 0; i
< nLen
; i
++ ) {
1430 nCryptMask
^= pStr
[i
];
1431 if( nCryptMask
& 0x80 ) {
1446 void SvStream::SetCryptMaskKey(const OString
& rCryptMaskKey
)
1448 m_aCryptMaskKey
= rCryptMaskKey
;
1449 m_nCryptMask
= implGetCryptMask(m_aCryptMaskKey
.getStr(),
1450 m_aCryptMaskKey
.getLength(), GetVersion());
1453 bool SvStream::SetStreamSize(sal_uInt64
const nSize
)
1456 sal_uInt64 nFPos
= Tell();
1458 sal_uInt16 nBuf
= m_nBufSize
;
1461 if (nSize
< m_nBufFilePos
)
1463 m_nBufFilePos
= nSize
;
1465 SetBufferSize( nBuf
);
1467 DBG_ASSERT(Tell()==nFPos
,"SetStreamSize failed");
1469 return (m_nError
== ERRCODE_NONE
);
1472 SvStream
& endl( SvStream
& rStr
)
1474 LineEnd eDelim
= rStr
.GetLineDelimiter();
1475 if ( eDelim
== LINEEND_CR
)
1476 rStr
.WriteChar('\r');
1477 else if( eDelim
== LINEEND_LF
)
1478 rStr
.WriteChar('\n');
1480 rStr
.WriteChar('\r').WriteChar('\n');
1484 SvStream
& endlu( SvStream
& rStrm
)
1486 switch ( rStrm
.GetLineDelimiter() )
1489 rStrm
.WriteUnicode('\r');
1492 rStrm
.WriteUnicode('\n');
1495 rStrm
.WriteUnicode('\r').WriteUnicode('\n');
1500 SvStream
& endlub( SvStream
& rStrm
)
1502 if ( rStrm
.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE
)
1503 return endlu( rStrm
);
1505 return endl( rStrm
);
1508 SvMemoryStream::SvMemoryStream( void* pBuffer
, std::size_t bufSize
,
1511 if( eMode
& StreamMode::WRITE
)
1512 m_isWritable
= true;
1514 m_isWritable
= false;
1515 nEndOfData
= bufSize
;
1517 pBuf
= static_cast<sal_uInt8
*>(pBuffer
);
1524 SvMemoryStream::SvMemoryStream( std::size_t nInitSize
, std::size_t nResizeOffset
)
1526 m_isWritable
= true;
1529 nResize
= nResizeOffset
;
1532 if( nResize
!= 0 && nResize
< 16 )
1535 AllocateMemory( nInitSize
);
1537 SetBufferSize( 64 );
1540 SvMemoryStream::~SvMemoryStream()
1551 void SvMemoryStream::SetBuffer( void* pNewBuf
, std::size_t nCount
,
1554 SetBufferSize( 0 ); // Init buffering in the base class
1556 if( bOwnsData
&& pNewBuf
!= pBuf
)
1559 pBuf
= static_cast<sal_uInt8
*>(pNewBuf
);
1572 std::size_t SvMemoryStream::GetData( void* pData
, std::size_t nCount
)
1574 std::size_t nMaxCount
= nEndOfData
-nPos
;
1575 if( nCount
> nMaxCount
)
1579 memcpy( pData
, pBuf
+nPos
, nCount
);
1585 std::size_t SvMemoryStream::PutData( const void* pData
, std::size_t nCount
)
1590 std::size_t nMaxCount
= nSize
-nPos
;
1592 // check for overflow
1593 if( nCount
> nMaxCount
)
1597 // copy as much as possible
1599 SetError( SVSTREAM_OUTOFMEMORY
);
1603 tools::Long nNewResize
;
1604 if( nSize
&& nSize
> nResize
)
1607 nNewResize
= nResize
;
1609 if( (nCount
-nMaxCount
) < nResize
)
1611 // lacking memory is smaller than nResize,
1612 // resize accordingly
1613 if( !ReAllocateMemory( nNewResize
) )
1616 SetError( SVSTREAM_WRITE_ERROR
);
1621 // lacking memory is larger than nResize,
1622 // resize by (nCount-nMaxCount) + resize offset
1623 if( !ReAllocateMemory( nCount
-nMaxCount
+nNewResize
) )
1626 SetError( SVSTREAM_WRITE_ERROR
);
1631 assert(pBuf
&& "Possibly Reallocate failed");
1632 memcpy( pBuf
+nPos
, pData
, nCount
);
1635 if( nPos
> nEndOfData
)
1640 sal_uInt64
SvMemoryStream::SeekPos(sal_uInt64
const nNewPos
)
1642 // nEndOfData: First position in stream not allowed to read from
1643 // nSize: Size of allocated buffer
1645 // check if a truncated STREAM_SEEK_TO_END was passed
1646 assert(nNewPos
!= SAL_MAX_UINT32
);
1647 if( nNewPos
< nEndOfData
)
1649 else if( nNewPos
== STREAM_SEEK_TO_END
)
1653 if( nNewPos
>= nSize
) // Does buffer need extension?
1655 if( nResize
) // Is extension possible?
1657 tools::Long nDiff
= static_cast<tools::Long
>(nNewPos
- nSize
+ 1);
1658 nDiff
+= static_cast<tools::Long
>(nResize
);
1659 ReAllocateMemory( nDiff
);
1661 nEndOfData
= nNewPos
;
1663 else // Extension not possible, set pos to end of data
1665 // SetError( SVSTREAM_OUTOFMEMORY );
1669 else // Expand buffer size
1672 nEndOfData
= nNewPos
;
1678 void SvMemoryStream::FlushData()
1682 void SvMemoryStream::ResetError()
1684 SvStream::ClearError();
1687 void SvMemoryStream::AllocateMemory( std::size_t nNewSize
)
1689 pBuf
= new sal_uInt8
[nNewSize
];
1692 // (using Bozo algorithm)
1693 bool SvMemoryStream::ReAllocateMemory( tools::Long nDiff
)
1695 if (!m_isWritable
|| !bOwnsData
)
1698 bool bRetVal
= false;
1699 tools::Long nTemp
= static_cast<tools::Long
>(nSize
);
1701 std::size_t nNewSize
= static_cast<std::size_t>(nTemp
);
1705 sal_uInt8
* pNewBuf
= new sal_uInt8
[nNewSize
];
1707 bRetVal
= true; // Success!
1708 if( nNewSize
< nSize
) // Are we shrinking?
1710 memcpy( pNewBuf
, pBuf
, nNewSize
);
1711 if( nPos
> nNewSize
)
1713 if( nEndOfData
>= nNewSize
)
1714 nEndOfData
= nNewSize
-1;
1720 memcpy( pNewBuf
, pBuf
, nSize
);
1722 memset(pNewBuf
+ nSize
, 0x00, nNewSize
- nSize
);
1743 void SvMemoryStream::FreeMemory()
1753 void* SvMemoryStream::SwitchBuffer()
1758 Seek( STREAM_SEEK_TO_BEGIN
);
1760 void* pRetVal
= pBuf
;
1768 std::size_t nInitSize
= 512;
1769 AllocateMemory(nInitSize
);
1772 SetBufferSize( 64 );
1776 void SvMemoryStream::SetSize(sal_uInt64
const nNewSize
)
1780 SetError(SVSTREAM_INVALID_HANDLE
);
1784 tools::Long nDiff
= static_cast<tools::Long
>(nNewSize
) - static_cast<tools::Long
>(nSize
);
1785 ReAllocateMemory( nDiff
);
1788 //Create an OString of nLen bytes from rStream
1789 OString
read_uInt8s_ToOString(SvStream
& rStrm
, std::size_t nLen
)
1791 rtl_String
*pStr
= nullptr;
1794 nLen
= std::min
<std::size_t>(nLen
, SAL_MAX_INT32
);
1795 //limit allocation to size of file, but + 1 to set eof state
1796 nLen
= std::min
<sal_uInt64
>(nLen
, rStrm
.remainingSize() + 1);
1797 //alloc a (ref-count 1) rtl_String of the desired length.
1798 //rtl_String's buffer is uninitialized, except for null termination
1799 pStr
= rtl_string_alloc(sal::static_int_cast
<sal_Int32
>(nLen
));
1800 SAL_WARN_IF(!pStr
, "tools.stream", "allocation failed");
1803 std::size_t nWasRead
= rStrm
.ReadBytes(pStr
->buffer
, nLen
);
1804 if (nWasRead
!= nLen
)
1806 //on (typically unlikely) short read set length to what we could
1807 //read, and null terminate. Excess buffer capacity remains of
1808 //course, could create a (true) replacement OString if it matters.
1809 pStr
->length
= sal::static_int_cast
<sal_Int32
>(nWasRead
);
1810 pStr
->buffer
[pStr
->length
] = 0;
1815 //take ownership of buffer and return, otherwise return empty string
1816 return pStr
? OString(pStr
, SAL_NO_ACQUIRE
) : OString();
1819 //Create an OUString of nLen sal_Unicode code units from rStream
1820 OUString
read_uInt16s_ToOUString(SvStream
& rStrm
, std::size_t nLen
)
1822 rtl_uString
*pStr
= nullptr;
1825 nLen
= std::min
<std::size_t>(nLen
, SAL_MAX_INT32
);
1826 //limit allocation to size of file, but + 1 to set eof state
1827 nLen
= o3tl::sanitizing_min
<sal_uInt64
>(nLen
, (rStrm
.remainingSize() + 2) / 2);
1828 //alloc a (ref-count 1) rtl_uString of the desired length.
1829 //rtl_String's buffer is uninitialized, except for null termination
1830 pStr
= rtl_uString_alloc(sal::static_int_cast
<sal_Int32
>(nLen
));
1831 SAL_WARN_IF(!pStr
, "tools.stream", "allocation failed");
1834 std::size_t nWasRead
= rStrm
.ReadBytes(pStr
->buffer
, nLen
*2)/2;
1835 if (nWasRead
!= nLen
)
1837 //on (typically unlikely) short read set length to what we could
1838 //read, and null terminate. Excess buffer capacity remains of
1839 //course, could create a (true) replacement OUString if it matters.
1840 pStr
->length
= sal::static_int_cast
<sal_Int32
>(nWasRead
);
1841 pStr
->buffer
[pStr
->length
] = 0;
1843 if (rStrm
.IsEndianSwap())
1845 for (sal_Int32 i
= 0; i
< pStr
->length
; ++i
)
1846 pStr
->buffer
[i
] = OSL_SWAPWORD(pStr
->buffer
[i
]);
1851 //take ownership of buffer and return, otherwise return empty string
1852 return pStr
? OUString(pStr
, SAL_NO_ACQUIRE
) : OUString();
1857 template <typename T
, typename O
> T
tmpl_convertLineEnd(const T
&rIn
, LineEnd eLineEnd
)
1859 // Determine linebreaks and compute length
1860 bool bConvert
= false; // Needs conversion
1861 sal_Int32 nStrLen
= rIn
.getLength();
1862 sal_Int32 nLineEndLen
= (eLineEnd
== LINEEND_CRLF
) ? 2 : 1;
1863 sal_Int32 nLen
= 0; // Target length
1864 sal_Int32 i
= 0; // Source counter
1868 // \r or \n causes linebreak
1869 if ( (rIn
[i
] == '\r') || (rIn
[i
] == '\n') )
1871 nLen
= nLen
+ nLineEndLen
;
1873 // If set already, skip expensive test
1876 // Do we need to convert?
1877 if ( ((eLineEnd
!= LINEEND_LF
) && (rIn
[i
] == '\n')) ||
1878 ((eLineEnd
== LINEEND_CRLF
) && (i
+1) < nStrLen
&& (rIn
[i
+1] != '\n')) ||
1879 ((eLineEnd
== LINEEND_LF
) &&
1880 ((rIn
[i
] == '\r') || ((i
+1) < nStrLen
&& rIn
[i
+1] == '\r'))) ||
1881 ((eLineEnd
== LINEEND_CR
) &&
1882 ((rIn
[i
] == '\n') || ((i
+1) < nStrLen
&& rIn
[i
+1] == '\n'))) )
1886 // skip char if \r\n or \n\r
1887 if ( (i
+1) < nStrLen
&& ((rIn
[i
+1] == '\r') || (rIn
[i
+1] == '\n')) &&
1888 (rIn
[i
] != rIn
[i
+1]) )
1899 // convert linebreaks, insert string
1904 // \r or \n causes linebreak
1905 if ( (rIn
[i
] == '\r') || (rIn
[i
] == '\n') )
1907 if ( eLineEnd
== LINEEND_CRLF
)
1909 aNewData
.append('\r');
1910 aNewData
.append('\n');
1914 if ( eLineEnd
== LINEEND_CR
)
1915 aNewData
.append('\r');
1917 aNewData
.append('\n');
1920 if ( (i
+1) < nStrLen
&& ((rIn
[i
+1] == '\r') || (rIn
[i
+1] == '\n')) &&
1921 (rIn
[i
] != rIn
[i
+1]) )
1926 aNewData
.append(rIn
[i
]);
1932 return aNewData
.makeStringAndClear();
1936 OString
convertLineEnd(const OString
&rIn
, LineEnd eLineEnd
)
1938 return tmpl_convertLineEnd
<OString
, OStringBuffer
>(rIn
, eLineEnd
);
1941 OUString
convertLineEnd(const OUString
&rIn
, LineEnd eLineEnd
)
1943 return tmpl_convertLineEnd
<OUString
, OUStringBuffer
>(rIn
, eLineEnd
);
1946 std::size_t write_uInt32_lenPrefixed_uInt16s_FromOUString(SvStream
& rStrm
,
1947 std::u16string_view rStr
)
1949 std::size_t nWritten
= 0;
1950 sal_uInt32 nUnits
= std::min
<std::size_t>(rStr
.size(), std::numeric_limits
<sal_uInt32
>::max());
1951 SAL_WARN_IF(static_cast<std::size_t>(nUnits
) != static_cast<std::size_t>(rStr
.size()),
1953 "string too long for prefix count to fit in output type");
1954 rStrm
.WriteUInt32(nUnits
);
1957 nWritten
+= sizeof(sal_uInt32
);
1958 nWritten
+= write_uInt16s_FromOUString(rStrm
, rStr
, nUnits
);
1963 std::size_t write_uInt16_lenPrefixed_uInt16s_FromOUString(SvStream
& rStrm
,
1964 std::u16string_view rStr
)
1966 std::size_t nWritten
= 0;
1967 sal_uInt16 nUnits
= std::min
<std::size_t>(rStr
.size(), std::numeric_limits
<sal_uInt16
>::max());
1968 SAL_WARN_IF(nUnits
!= rStr
.size(),
1970 "string too long for prefix count to fit in output type");
1971 rStrm
.WriteUInt16(nUnits
);
1974 nWritten
+= sizeof(nUnits
);
1975 nWritten
+= write_uInt16s_FromOUString(rStrm
, rStr
, nUnits
);
1980 std::size_t write_uInt16_lenPrefixed_uInt8s_FromOString(SvStream
& rStrm
,
1981 std::string_view rStr
)
1983 std::size_t nWritten
= 0;
1984 sal_uInt16 nUnits
= std::min
<std::size_t>(rStr
.size(), std::numeric_limits
<sal_uInt16
>::max());
1985 SAL_WARN_IF(static_cast<std::size_t>(nUnits
) != static_cast<std::size_t>(rStr
.size()),
1987 "string too long for sal_uInt16 count to fit in output type");
1988 rStrm
.WriteUInt16( nUnits
);
1991 nWritten
+= sizeof(sal_uInt16
);
1992 nWritten
+= write_uInt8s_FromOString(rStrm
, rStr
, nUnits
);
1997 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */