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()
164 ErrCode
SvLockBytes::ReadAt(sal_uInt64
const , void * , std::size_t ,
165 std::size_t * ) const
167 OSL_FAIL("SvLockBytes::ReadAt(): Bad stream");
172 ErrCode
SvLockBytes::WriteAt(sal_uInt64
const , const void * , std::size_t ,
175 OSL_FAIL("SvLockBytes::WriteAt(): Bad stream");
180 ErrCode
SvLockBytes::Flush() const
182 OSL_FAIL("SvLockBytes::Flush(): Bad stream");
187 ErrCode
SvLockBytes::SetSize(sal_uInt64
)
189 OSL_FAIL("SvLockBytes::SetSize(): Bad stream");
193 ErrCode
SvLockBytes::Stat(SvLockBytesStat
*) const
195 OSL_FAIL("SvLockBytes::Stat(): Bad stream");
200 std::size_t SvStream::GetData( void* pData
, std::size_t nSize
)
204 DBG_ASSERT( m_xLockBytes
.is(), "pure virtual function" );
206 m_nError
= m_xLockBytes
->ReadAt(m_nActPos
, pData
, nSize
, &nRet
);
213 std::size_t SvStream::PutData( const void* pData
, std::size_t nSize
)
217 DBG_ASSERT( m_xLockBytes
.is(), "pure virtual function" );
219 m_nError
= m_xLockBytes
->WriteAt(m_nActPos
, pData
, nSize
, &nRet
);
226 sal_uInt64
SvStream::SeekPos(sal_uInt64
const nPos
)
228 // check if a truncated STREAM_SEEK_TO_END was passed
229 assert(nPos
!= SAL_MAX_UINT32
);
230 if( !GetError() && nPos
== STREAM_SEEK_TO_END
)
232 DBG_ASSERT( m_xLockBytes
.is(), "pure virtual function" );
233 SvLockBytesStat aStat
;
234 m_xLockBytes
->Stat( &aStat
);
235 m_nActPos
= aStat
.nSize
;
242 void SvStream::FlushData()
246 DBG_ASSERT( m_xLockBytes
.is(), "pure virtual function" );
247 m_nError
= m_xLockBytes
->Flush();
251 void SvStream::SetSize(sal_uInt64
const nSize
)
253 DBG_ASSERT( m_xLockBytes
.is(), "pure virtual function" );
254 m_nError
= m_xLockBytes
->SetSize( nSize
);
257 SvStream::SvStream() :
271 , m_nCompressMode(SvStreamCompressFlags::NONE
)
273 , m_eLineDelimiter(LINEEND_LF
) // UNIX-Format
275 , m_eLineDelimiter(LINEEND_CRLF
) // DOS-Format
277 , m_eStreamCharSet(osl_getThreadTextEncoding())
284 , m_eStreamMode(StreamMode::NONE
)
288 SetEndian( SvStreamEndian::LITTLE
);
293 SvStream::SvStream( SvLockBytes
* pLockBytesP
) : SvStream()
295 m_xLockBytes
= pLockBytesP
;
296 SetBufferSize( 256 );
299 SvStream::~SvStream()
301 if (m_xLockBytes
.is())
305 void SvStream::ClearError()
308 m_nError
= ERRCODE_NONE
;
311 void SvStream::SetError( ErrCode nErrorCode
)
313 if (m_nError
== ERRCODE_NONE
|| (m_nError
.IsWarning() && nErrorCode
.IsError()))
314 m_nError
= nErrorCode
;
317 void SvStream::SetEndian( SvStreamEndian nNewFormat
)
320 m_isSwap
= nNewFormat
== SvStreamEndian::LITTLE
;
322 m_isSwap
= nNewFormat
== SvStreamEndian::BIG
;
326 SvStreamEndian
SvStream::GetEndian() const
329 return m_isSwap
? SvStreamEndian::LITTLE
: SvStreamEndian::BIG
;
331 return m_isSwap
? SvStreamEndian::BIG
: SvStreamEndian::LITTLE
;
335 void SvStream::SetBufferSize( sal_uInt16 nBufferSize
)
337 sal_uInt64
const nActualFilePos
= Tell();
338 bool bDontSeek
= (m_pRWBuf
== nullptr);
340 if (m_isDirty
&& m_isWritable
) // due to Windows NT: Access denied
346 m_nBufFilePos
+= m_nBufActualPos
;
352 m_nBufSize
= nBufferSize
;
354 m_pRWBuf
.reset(new sal_uInt8
[ m_nBufSize
]);
355 m_pBufPos
= m_pRWBuf
.get();
356 m_isIoRead
= m_isIoWrite
= false;
358 SeekPos( nActualFilePos
);
361 void SvStream::ClearBuffer()
366 m_pBufPos
= m_pRWBuf
.get();
368 m_isIoRead
= m_isIoWrite
= false;
373 void SvStream::ResetError()
378 bool SvStream::ReadByteStringLine( OUString
& rStr
, rtl_TextEncoding eSrcCharSet
,
379 sal_Int32 nMaxBytesToRead
)
382 bool bRet
= ReadLine( aStr
, nMaxBytesToRead
);
383 rStr
= OStringToOUString(aStr
, eSrcCharSet
);
387 bool SvStream::ReadLine( OString
& rStr
, sal_Int32 nMaxBytesToRead
)
389 OStringBuffer
aBuf(4096);
390 bool rv
= ReadLine(aBuf
, nMaxBytesToRead
);
391 rStr
= aBuf
.makeStringAndClear();
395 bool SvStream::ReadLine( OStringBuffer
& aBuf
, sal_Int32 nMaxBytesToRead
)
399 sal_uInt64 nOldFilePos
= Tell();
401 std::size_t nTotalLen
= 0;
404 while( !bEnd
&& !GetError() ) // Don't test for EOF as we
405 // are reading block-wise!
407 sal_uInt16 nLen
= static_cast<sal_uInt16
>(ReadBytes(buf
, sizeof(buf
)-1));
410 if ( aBuf
.isEmpty() )
412 // Exit on first block-read error
422 for( j
= n
= 0; j
< nLen
; ++j
)
425 if ( c
== '\n' || c
== '\r' )
435 if (nTotalLen
> o3tl::make_unsigned(nMaxBytesToRead
))
437 n
-= nTotalLen
- nMaxBytesToRead
;
438 nTotalLen
= nMaxBytesToRead
;
445 if ( !bEnd
&& !GetError() && !aBuf
.isEmpty() )
448 nOldFilePos
+= nTotalLen
;
449 if( Tell() > nOldFilePos
)
451 Seek( nOldFilePos
); // Seek pointer due to BlockRead above
453 if ( bEnd
&& (c
=='\r' || c
=='\n') ) // Special treatment for DOS files
456 std::size_t nLen
= ReadBytes(&cTemp
, sizeof(cTemp
));
458 if( cTemp
== c
|| (cTemp
!= '\n' && cTemp
!= '\r') )
468 bool SvStream::ReadUniStringLine( OUString
& rStr
, sal_Int32 nMaxCodepointsToRead
)
470 sal_Unicode buf
[256+1];
472 sal_uInt64 nOldFilePos
= Tell();
474 std::size_t nTotalLen
= 0;
476 DBG_ASSERT( sizeof(sal_Unicode
) == sizeof(sal_uInt16
), "ReadUniStringLine: swapping sizeof(sal_Unicode) not implemented" );
478 OUStringBuffer
aBuf(4096);
479 while( !bEnd
&& !GetError() ) // Don't test for EOF as we
480 // are reading block-wise!
482 sal_uInt16 nLen
= static_cast<sal_uInt16
>(ReadBytes( buf
, sizeof(buf
)-sizeof(sal_Unicode
)));
483 nLen
/= sizeof(sal_Unicode
);
486 if ( aBuf
.isEmpty() )
488 // exit on first BlockRead error
498 for( j
= n
= 0; j
< nLen
; ++j
)
501 SwapNumber( buf
[n
] );
503 if ( c
== '\n' || c
== '\r' )
508 // erAck 26.02.01: Old behavior was no special treatment of '\0'
509 // character here, but a following rStr+=c did ignore it. Is this
510 // really intended? Or should a '\0' better terminate a line?
511 // The nOldFilePos stuff wasn't correct then anyways.
520 if (nTotalLen
> o3tl::make_unsigned(nMaxCodepointsToRead
))
522 n
-= nTotalLen
- nMaxCodepointsToRead
;
523 nTotalLen
= nMaxCodepointsToRead
;
527 aBuf
.append( buf
, n
);
530 if ( !bEnd
&& !GetError() && !aBuf
.isEmpty() )
533 nOldFilePos
+= nTotalLen
* sizeof(sal_Unicode
);
534 if( Tell() > nOldFilePos
)
535 nOldFilePos
+= sizeof(sal_Unicode
);
536 Seek( nOldFilePos
); // seek due to BlockRead above
538 if ( bEnd
&& (c
=='\r' || c
=='\n') ) // special treatment for DOS files
541 ReadBytes( &cTemp
, sizeof(cTemp
) );
544 if( cTemp
== c
|| (cTemp
!= '\n' && cTemp
!= '\r') )
550 rStr
= aBuf
.makeStringAndClear();
554 bool SvStream::ReadUniOrByteStringLine( OUString
& rStr
, rtl_TextEncoding eSrcCharSet
,
555 sal_Int32 nMaxCodepointsToRead
)
557 if ( eSrcCharSet
== RTL_TEXTENCODING_UNICODE
)
558 return ReadUniStringLine( rStr
, nMaxCodepointsToRead
);
560 return ReadByteStringLine( rStr
, eSrcCharSet
, nMaxCodepointsToRead
);
563 OString
read_zeroTerminated_uInt8s_ToOString(SvStream
& rStream
)
565 OStringBuffer
aOutput(256);
569 sal_uInt64 nFilePos
= rStream
.Tell();
571 while( !bEnd
&& !rStream
.GetError() )
573 std::size_t nLen
= rStream
.ReadBytes(buf
, sizeof(buf
)-1);
577 std::size_t nReallyRead
= nLen
;
578 const char* pPtr
= buf
;
579 while (nLen
&& *pPtr
)
585 bEnd
= ( nReallyRead
< sizeof(buf
)-1 ) // read less than attempted to read
586 || ( ( nLen
> 0 ) // OR it is inside the block we read
587 && ( 0 == *pPtr
) // AND found a string terminator
590 aOutput
.append(buf
, pPtr
- buf
);
593 nFilePos
+= aOutput
.getLength();
594 if (rStream
.Tell() > nFilePos
)
595 rStream
.Seek(nFilePos
+1); // seek due to FileRead above
596 return aOutput
.makeStringAndClear();
599 OUString
read_zeroTerminated_uInt8s_ToOUString(SvStream
& rStream
, rtl_TextEncoding eEnc
)
601 return OStringToOUString(
602 read_zeroTerminated_uInt8s_ToOString(rStream
), eEnc
);
605 /** Attempt to write a sequence of nUnits 16bit units from an OUString,
606 returned value is number of bytes written */
607 static std::size_t write_uInt16s_FromOUString(SvStream
& rStrm
, std::u16string_view rStr
,
610 DBG_ASSERT( sizeof(sal_Unicode
) == sizeof(sal_uInt16
), "write_uInt16s_FromOUString: swapping sizeof(sal_Unicode) not implemented" );
611 std::size_t nWritten
;
612 if (!rStrm
.IsEndianSwap())
613 nWritten
= rStrm
.WriteBytes(rStr
.data(), nUnits
* sizeof(sal_Unicode
));
616 std::size_t nLen
= nUnits
;
617 sal_Unicode aBuf
[384];
618 sal_Unicode
* const pTmp
= ( nLen
> 384 ? new sal_Unicode
[nLen
] : aBuf
);
619 memcpy( pTmp
, rStr
.data(), nLen
* sizeof(sal_Unicode
) );
620 sal_Unicode
* p
= pTmp
;
621 const sal_Unicode
* const pStop
= pTmp
+ nLen
;
627 nWritten
= rStrm
.WriteBytes( pTmp
, nLen
* sizeof(sal_Unicode
) );
634 bool SvStream::WriteUnicodeOrByteText(std::u16string_view rStr
, rtl_TextEncoding eDestCharSet
, bool bZero
)
636 if ( eDestCharSet
== RTL_TEXTENCODING_UNICODE
)
638 write_uInt16s_FromOUString(*this, rStr
, rStr
.size());
644 OString
aStr(OUStringToOString(rStr
, eDestCharSet
));
645 WriteBytes(aStr
.getStr(), aStr
.getLength());
649 return m_nError
== ERRCODE_NONE
;
652 bool SvStream::WriteByteStringLine( std::u16string_view rStr
, rtl_TextEncoding eDestCharSet
)
654 return WriteLine(OUStringToOString(rStr
, eDestCharSet
));
657 bool SvStream::WriteLine(std::string_view rStr
)
659 WriteBytes(rStr
.data(), rStr
.size());
661 return m_nError
== ERRCODE_NONE
;
664 bool SvStream::WriteUniOrByteChar( sal_Unicode ch
, rtl_TextEncoding eDestCharSet
)
666 if ( eDestCharSet
== RTL_TEXTENCODING_UNICODE
)
670 OString
aStr(&ch
, 1, eDestCharSet
);
671 WriteBytes(aStr
.getStr(), aStr
.getLength());
673 return m_nError
== ERRCODE_NONE
;
676 void SvStream::StartWritingUnicodeText()
678 m_isSwap
= false; // Switch to no endian swapping
679 // BOM, Byte Order Mark, U+FEFF, see
680 // http://www.unicode.org/faq/utf_bom.html#BOM
681 // Upon read: 0xfeff(-257) => no swap; 0xfffe(-2) => swap
685 void SvStream::StartReadingUnicodeText( rtl_TextEncoding eReadBomCharSet
)
687 if (!( eReadBomCharSet
== RTL_TEXTENCODING_DONTKNOW
||
688 eReadBomCharSet
== RTL_TEXTENCODING_UNICODE
||
689 eReadBomCharSet
== RTL_TEXTENCODING_UTF8
))
690 return; // nothing to read
692 const sal_uInt64 nOldPos
= Tell();
693 bool bGetBack
= true;
694 unsigned char nFlag(0);
698 case 0xfe: // UTF-16BE?
699 if ( eReadBomCharSet
== RTL_TEXTENCODING_DONTKNOW
||
700 eReadBomCharSet
== RTL_TEXTENCODING_UNICODE
)
705 SetEndian(SvStreamEndian::BIG
);
710 case 0xff: // UTF-16LE?
711 if ( eReadBomCharSet
== RTL_TEXTENCODING_DONTKNOW
||
712 eReadBomCharSet
== RTL_TEXTENCODING_UNICODE
)
717 SetEndian(SvStreamEndian::LITTLE
);
723 if ( eReadBomCharSet
== RTL_TEXTENCODING_DONTKNOW
||
724 eReadBomCharSet
== RTL_TEXTENCODING_UTF8
)
731 bGetBack
= false; // it is UTF-8
739 Seek(nOldPos
); // no BOM, pure data
742 sal_uInt64
SvStream::SeekRel(sal_Int64
const nPos
)
744 sal_uInt64 nActualPos
= Tell();
748 if (SAL_MAX_UINT64
- nActualPos
> o3tl::make_unsigned(nPos
))
753 sal_uInt64
const nAbsPos
= static_cast<sal_uInt64
>(-nPos
);
754 if ( nActualPos
>= nAbsPos
)
755 nActualPos
-= nAbsPos
;
758 assert((m_pBufPos
!= nullptr) == bool(m_pRWBuf
));
761 m_pBufPos
= m_pRWBuf
.get() + nActualPos
;
763 return Seek( nActualPos
);
766 template <typename T
> SvStream
& SvStream::ReadNumber(T
& r
)
769 readNumberWithoutSwap(n
);
779 SvStream
& SvStream::ReadUInt16(sal_uInt16
& r
) { return ReadNumber(r
); }
780 SvStream
& SvStream::ReadUInt32(sal_uInt32
& r
) { return ReadNumber(r
); }
781 SvStream
& SvStream::ReadUInt64(sal_uInt64
& r
) { return ReadNumber(r
); }
782 SvStream
& SvStream::ReadInt16(sal_Int16
& r
) { return ReadNumber(r
); }
783 SvStream
& SvStream::ReadInt32(sal_Int32
& r
) { return ReadNumber(r
); }
784 SvStream
& SvStream::ReadInt64(sal_Int64
& r
) { return ReadNumber(r
); }
786 SvStream
& SvStream::ReadSChar( signed char& r
)
788 if (m_isIoRead
&& sizeof(signed char) <= m_nBufFree
)
791 m_nBufActualPos
+= sizeof(signed char);
792 m_pBufPos
+= sizeof(signed char);
793 m_nBufFree
-= sizeof(signed char);
796 ReadBytes( &r
, sizeof(signed char) );
800 // Special treatment for Chars due to PutBack
802 SvStream
& SvStream::ReadChar( char& r
)
804 if (m_isIoRead
&& sizeof(char) <= m_nBufFree
)
807 m_nBufActualPos
+= sizeof(char);
808 m_pBufPos
+= sizeof(char);
809 m_nBufFree
-= sizeof(char);
812 ReadBytes( &r
, sizeof(char) );
816 SvStream
& SvStream::ReadUChar( unsigned char& r
)
818 if (m_isIoRead
&& sizeof(char) <= m_nBufFree
)
821 m_nBufActualPos
+= sizeof(char);
822 m_pBufPos
+= sizeof(char);
823 m_nBufFree
-= sizeof(char);
826 ReadBytes( &r
, sizeof(char) );
830 SvStream
& SvStream::ReadUtf16(sal_Unicode
& r
) { return ReadNumber(r
); }
832 SvStream
& SvStream::ReadCharAsBool( bool& r
)
834 if (m_isIoRead
&& sizeof(char) <= m_nBufFree
)
837 *m_pBufPos
> 1, "tools.stream", unsigned(*m_pBufPos
) << " not 0/1");
839 m_nBufActualPos
+= sizeof(char);
840 m_pBufPos
+= sizeof(char);
841 m_nBufFree
-= sizeof(char);
846 if (ReadBytes(&c
, 1) == 1)
848 SAL_WARN_IF(c
> 1, "tools.stream", unsigned(c
) << " not 0/1");
855 SvStream
& SvStream::ReadFloat(float& r
)
858 readNumberWithoutSwap(n
);
870 SvStream
& SvStream::ReadDouble(double& r
)
873 readNumberWithoutSwap(n
);
885 SvStream
& SvStream::ReadStream( SvStream
& rStream
)
887 const sal_uInt32 cBufLen
= 0x8000;
888 std::unique_ptr
<char[]> pBuf( new char[ cBufLen
] );
892 nCount
= ReadBytes( pBuf
.get(), cBufLen
);
893 rStream
.WriteBytes( pBuf
.get(), nCount
);
894 } while( nCount
== cBufLen
);
899 template <typename T
> SvStream
& SvStream::WriteNumber(T n
)
903 writeNumberWithoutSwap(n
);
907 SvStream
& SvStream::WriteUInt16(sal_uInt16 v
) { return WriteNumber(v
); }
908 SvStream
& SvStream::WriteUInt32(sal_uInt32 v
) { return WriteNumber(v
); }
909 SvStream
& SvStream::WriteUInt64(sal_uInt64 v
) { return WriteNumber(v
); }
910 SvStream
& SvStream::WriteInt16(sal_Int16 v
) { return WriteNumber(v
); }
911 SvStream
& SvStream::WriteInt32(sal_Int32 v
) { return WriteNumber(v
); }
912 SvStream
& SvStream::WriteInt64(sal_Int64 v
) { return WriteNumber(v
); }
914 SvStream
& SvStream::WriteSChar( signed char v
)
917 if (m_isIoWrite
&& sizeof(signed char) <= m_nBufFree
)
920 m_pBufPos
++; // sizeof(char);
922 if (m_nBufActualPos
> m_nBufActualLen
) // Append ?
923 m_nBufActualLen
= m_nBufActualPos
;
924 m_nBufFree
--; // = sizeof(char);
928 WriteBytes( &v
, sizeof(signed char) );
932 // Special treatment for Chars due to PutBack
934 SvStream
& SvStream::WriteChar( char v
)
937 if (m_isIoWrite
&& sizeof(char) <= m_nBufFree
)
940 m_pBufPos
++; // sizeof(char);
942 if (m_nBufActualPos
> m_nBufActualLen
) // Append ?
943 m_nBufActualLen
= m_nBufActualPos
;
944 m_nBufFree
--; // = sizeof(char);
948 WriteBytes( &v
, sizeof(char) );
952 SvStream
& SvStream::WriteUChar( unsigned char v
)
955 if (m_isIoWrite
&& sizeof(char) <= m_nBufFree
)
957 *reinterpret_cast<unsigned char*>(m_pBufPos
) = v
;
958 m_pBufPos
++; // = sizeof(char);
959 m_nBufActualPos
++; // = sizeof(char);
960 if (m_nBufActualPos
> m_nBufActualLen
) // Append ?
961 m_nBufActualLen
= m_nBufActualPos
;
966 WriteBytes( &v
, sizeof(char) );
970 SvStream
& SvStream::WriteUInt8( sal_uInt8 v
)
972 return WriteUChar(v
);
975 SvStream
& SvStream::WriteUnicode( sal_Unicode v
)
977 return WriteUInt16(v
);
980 SvStream
& SvStream::WriteFloat( float v
)
986 writeNumberWithoutSwap(v
);
990 SvStream
& SvStream::WriteDouble ( double v
)
996 writeNumberWithoutSwap(v
);
1000 SvStream
& SvStream::WriteStream( SvStream
& rStream
)
1002 const sal_uInt32 cBufLen
= 0x8000;
1003 std::unique_ptr
<char[]> pBuf( new char[ cBufLen
] );
1006 nCount
= rStream
.ReadBytes( pBuf
.get(), cBufLen
);
1007 WriteBytes( pBuf
.get(), nCount
);
1008 } while( nCount
== cBufLen
);
1013 sal_uInt64
SvStream::WriteStream( SvStream
& rStream
, sal_uInt64 nSize
)
1015 const sal_uInt32 cBufLen
= 0x8000;
1016 std::unique_ptr
<char[]> pBuf( new char[ cBufLen
] );
1017 sal_uInt32 nCurBufLen
= cBufLen
;
1019 sal_uInt64 nWriteSize
= nSize
;
1023 nCurBufLen
= std::min
<sal_uInt64
>(nCurBufLen
, nWriteSize
);
1024 nCount
= rStream
.ReadBytes(pBuf
.get(), nCurBufLen
);
1025 WriteBytes( pBuf
.get(), nCount
);
1026 nWriteSize
-= nCount
;
1028 while( nWriteSize
&& nCount
== nCurBufLen
);
1030 return nSize
- nWriteSize
;
1033 OUString
SvStream::ReadUniOrByteString( rtl_TextEncoding eSrcCharSet
)
1035 // read UTF-16 string directly from stream ?
1036 if (eSrcCharSet
== RTL_TEXTENCODING_UNICODE
)
1037 return read_uInt32_lenPrefixed_uInt16s_ToOUString(*this);
1038 return read_uInt16_lenPrefixed_uInt8s_ToOUString(*this, eSrcCharSet
);
1041 SvStream
& SvStream::WriteUniOrByteString( std::u16string_view rStr
, rtl_TextEncoding eDestCharSet
)
1043 // write UTF-16 string directly into stream ?
1044 if (eDestCharSet
== RTL_TEXTENCODING_UNICODE
)
1045 write_uInt32_lenPrefixed_uInt16s_FromOUString(*this, rStr
);
1047 write_uInt16_lenPrefixed_uInt8s_FromOUString(*this, rStr
, eDestCharSet
);
1051 void SvStream::FlushBuffer()
1053 if (m_isDirty
) // Does stream require a flush?
1055 SeekPos(m_nBufFilePos
);
1057 CryptAndWriteBuffer(m_pRWBuf
.get(), m_nBufActualLen
);
1058 else if (PutData(m_pRWBuf
.get(), m_nBufActualLen
) != m_nBufActualLen
)
1059 SetError(SVSTREAM_WRITE_ERROR
);
1064 std::size_t SvStream::ReadBytes( void* pData
, std::size_t nCount
)
1066 std::size_t nSaveCount
= nCount
;
1070 nCount
= GetData( pData
,nCount
);
1072 EncryptBuffer(pData
, nCount
);
1073 m_nBufFilePos
+= nCount
;
1077 // check if block is completely within buffer
1079 m_isIoWrite
= false;
1080 if (nCount
<= o3tl::make_unsigned(m_nBufActualLen
- m_nBufActualPos
))
1084 memcpy(pData
, m_pBufPos
, nCount
);
1085 m_nBufActualPos
= m_nBufActualPos
+ static_cast<sal_uInt16
>(nCount
);
1086 m_pBufPos
+= nCount
;
1087 m_nBufFree
= m_nBufFree
- static_cast<sal_uInt16
>(nCount
);
1093 // Does data block fit into buffer?
1094 if (nCount
> m_nBufSize
)
1096 // => No! Thus read directly
1097 // into target area without using the buffer
1101 SeekPos(m_nBufFilePos
+ m_nBufActualPos
);
1102 m_nBufActualLen
= 0;
1103 m_pBufPos
= m_pRWBuf
.get();
1104 nCount
= GetData( pData
, nCount
);
1106 EncryptBuffer(pData
, nCount
);
1107 m_nBufFilePos
+= nCount
;
1108 m_nBufFilePos
+= m_nBufActualPos
;
1109 m_nBufActualPos
= 0;
1113 // => Yes. Fill buffer first, then copy to target area
1115 m_nBufFilePos
+= m_nBufActualPos
;
1116 SeekPos(m_nBufFilePos
);
1118 // TODO: Typecast before GetData, sal_uInt16 nCountTmp
1119 std::size_t nCountTmp
= GetData( m_pRWBuf
.get(), m_nBufSize
);
1121 EncryptBuffer(m_pRWBuf
.get(), nCountTmp
);
1122 m_nBufActualLen
= static_cast<sal_uInt16
>(nCountTmp
);
1123 if( nCount
> nCountTmp
)
1125 nCount
= nCountTmp
; // trim count back, EOF see below
1127 memcpy( pData
, m_pRWBuf
.get(), nCount
);
1128 m_nBufActualPos
= static_cast<sal_uInt16
>(nCount
);
1129 m_pBufPos
= m_pRWBuf
.get() + nCount
;
1134 m_nBufFree
= m_nBufActualLen
- m_nBufActualPos
;
1135 if (nCount
!= nSaveCount
&& m_nError
!= ERRCODE_IO_PENDING
)
1137 if (nCount
== nSaveCount
&& m_nError
== ERRCODE_IO_PENDING
)
1138 m_nError
= ERRCODE_NONE
;
1142 std::size_t SvStream::WriteBytes( const void* pData
, std::size_t nCount
)
1149 SetError( ERRCODE_IO_CANTWRITE
);
1156 nCount
= CryptAndWriteBuffer( pData
, nCount
);
1158 nCount
= PutData( pData
, nCount
);
1159 m_nBufFilePos
+= nCount
;
1165 if (nCount
<= o3tl::make_unsigned(m_nBufSize
- m_nBufActualPos
))
1167 memcpy( m_pBufPos
, pData
, nCount
);
1168 m_nBufActualPos
= m_nBufActualPos
+ static_cast<sal_uInt16
>(nCount
);
1169 // Update length if buffer was updated
1170 if (m_nBufActualPos
> m_nBufActualLen
)
1171 m_nBufActualLen
= m_nBufActualPos
;
1173 m_pBufPos
+= nCount
;
1180 // Does data block fit into buffer?
1181 if (nCount
> m_nBufSize
)
1183 m_isIoWrite
= false;
1184 m_nBufFilePos
+= m_nBufActualPos
;
1185 m_nBufActualLen
= 0;
1186 m_nBufActualPos
= 0;
1187 m_pBufPos
= m_pRWBuf
.get();
1188 SeekPos(m_nBufFilePos
);
1190 nCount
= CryptAndWriteBuffer( pData
, nCount
);
1192 nCount
= PutData( pData
, nCount
);
1193 m_nBufFilePos
+= nCount
;
1197 // Copy block to buffer
1198 memcpy( m_pRWBuf
.get(), pData
, nCount
);
1201 m_nBufFilePos
+= m_nBufActualPos
;
1202 m_nBufActualPos
= static_cast<sal_uInt16
>(nCount
);
1203 m_pBufPos
= m_pRWBuf
.get() + nCount
;
1204 m_nBufActualLen
= static_cast<sal_uInt16
>(nCount
);
1208 m_nBufFree
= m_nBufSize
- m_nBufActualPos
;
1212 sal_uInt64
SvStream::Seek(sal_uInt64
const nFilePos
)
1214 m_isIoRead
= m_isIoWrite
= false;
1218 m_nBufFilePos
= SeekPos( nFilePos
);
1219 DBG_ASSERT(Tell() == m_nBufFilePos
,"Out Of Sync!");
1220 return m_nBufFilePos
;
1223 // Is seek position within buffer?
1224 if (nFilePos
>= m_nBufFilePos
&& nFilePos
<= (m_nBufFilePos
+ m_nBufActualLen
))
1226 m_nBufActualPos
= static_cast<sal_uInt16
>(nFilePos
- m_nBufFilePos
);
1227 m_pBufPos
= m_pRWBuf
.get() + m_nBufActualPos
;
1228 // Update m_nBufFree to avoid crash upon PutBack
1229 m_nBufFree
= m_nBufActualLen
- m_nBufActualPos
;
1234 m_nBufActualLen
= 0;
1235 m_nBufActualPos
= 0;
1236 m_pBufPos
= m_pRWBuf
.get();
1237 m_nBufFilePos
= SeekPos( nFilePos
);
1239 return m_nBufFilePos
+ m_nBufActualPos
;
1242 bool checkSeek(SvStream
&rSt
, sal_uInt64 nOffset
)
1244 const sal_uInt64 nMaxSeek
= rSt
.TellEnd();
1245 return (nOffset
<= nMaxSeek
&& rSt
.Seek(nOffset
) == nOffset
);
1250 bool isEmptyFileUrl(const OUString
& rUrl
)
1252 if (!comphelper::isFileUrl(rUrl
))
1257 SvFileStream
aStream(rUrl
, StreamMode::READ
);
1258 if (!aStream
.IsOpen())
1263 return aStream
.remainingSize() == 0;
1267 //STREAM_SEEK_TO_END in some of the Seek backends is special cased to be
1268 //efficient, in others e.g. SotStorageStream it's really horribly slow, and in
1269 //those this should be overridden
1270 sal_uInt64
SvStream::remainingSize()
1272 sal_uInt64
const nCurr
= Tell();
1273 sal_uInt64
const nEnd
= TellEnd();
1274 sal_uInt64 nMaxAvailable
= nEnd
> nCurr
? (nEnd
-nCurr
) : 0;
1275 return nMaxAvailable
;
1278 sal_uInt64
SvStream::TellEnd()
1281 sal_uInt64
const nCurr
= Tell();
1282 sal_uInt64
const nEnd
= Seek(STREAM_SEEK_TO_END
);
1287 void SvStream::Flush()
1294 void SvStream::RefreshBuffer()
1297 SeekPos(m_nBufFilePos
);
1298 m_nBufActualLen
= static_cast<sal_uInt16
>(GetData( m_pRWBuf
.get(), m_nBufSize
));
1299 if (m_nBufActualLen
&& m_nError
== ERRCODE_IO_PENDING
)
1300 m_nError
= ERRCODE_NONE
;
1302 EncryptBuffer(m_pRWBuf
.get(), static_cast<std::size_t>(m_nBufActualLen
));
1303 m_isIoRead
= m_isIoWrite
= false;
1306 #define CRYPT_BUFSIZE 1024
1308 /// Encrypt and write
1309 std::size_t SvStream::CryptAndWriteBuffer( const void* pStart
, std::size_t nLen
)
1311 unsigned char pTemp
[CRYPT_BUFSIZE
];
1312 unsigned char const * pDataPtr
= static_cast<unsigned char const *>(pStart
);
1313 std::size_t nCount
= 0;
1314 std::size_t nBufCount
;
1315 unsigned char nMask
= m_nCryptMask
;
1318 if( nLen
>= CRYPT_BUFSIZE
)
1319 nBufCount
= CRYPT_BUFSIZE
;
1323 memcpy( pTemp
, pDataPtr
, static_cast<sal_uInt16
>(nBufCount
) );
1324 // ******** Encrypt ********
1325 for (unsigned char & rn
: pTemp
)
1327 unsigned char aCh
= rn
;
1332 // *************************
1333 nCount
+= PutData( pTemp
, nBufCount
);
1334 pDataPtr
+= nBufCount
;
1340 void SvStream::EncryptBuffer(void* pStart
, std::size_t nLen
) const
1342 unsigned char* pTemp
= static_cast<unsigned char*>(pStart
);
1343 unsigned char nMask
= m_nCryptMask
;
1345 for ( std::size_t n
=0; n
< nLen
; n
++, pTemp
++ )
1347 unsigned char aCh
= *pTemp
;
1354 static unsigned char implGetCryptMask(const char* pStr
, sal_Int32 nLen
, tools::Long nVersion
)
1356 unsigned char nCryptMask
= 0;
1361 if( nVersion
<= SOFFICE_FILEFORMAT_31
)
1365 nCryptMask
^= *pStr
;
1370 else // BugFix #25888#
1372 for( sal_Int32 i
= 0; i
< nLen
; i
++ ) {
1373 nCryptMask
^= pStr
[i
];
1374 if( nCryptMask
& 0x80 ) {
1389 void SvStream::SetCryptMaskKey(const OString
& rCryptMaskKey
)
1391 m_aCryptMaskKey
= rCryptMaskKey
;
1392 m_nCryptMask
= implGetCryptMask(m_aCryptMaskKey
.getStr(),
1393 m_aCryptMaskKey
.getLength(), GetVersion());
1396 bool SvStream::SetStreamSize(sal_uInt64
const nSize
)
1399 sal_uInt64 nFPos
= Tell();
1401 sal_uInt16 nBuf
= m_nBufSize
;
1404 if (nSize
< m_nBufFilePos
)
1406 m_nBufFilePos
= nSize
;
1408 SetBufferSize( nBuf
);
1410 DBG_ASSERT(Tell()==nFPos
,"SetStreamSize failed");
1412 return (m_nError
== ERRCODE_NONE
);
1415 SvStream
& endl( SvStream
& rStr
)
1417 LineEnd eDelim
= rStr
.GetLineDelimiter();
1418 if ( eDelim
== LINEEND_CR
)
1419 rStr
.WriteChar('\r');
1420 else if( eDelim
== LINEEND_LF
)
1421 rStr
.WriteChar('\n');
1423 rStr
.WriteChar('\r').WriteChar('\n');
1427 SvStream
& endlu( SvStream
& rStrm
)
1429 switch ( rStrm
.GetLineDelimiter() )
1432 rStrm
.WriteUnicode('\r');
1435 rStrm
.WriteUnicode('\n');
1438 rStrm
.WriteUnicode('\r').WriteUnicode('\n');
1443 SvStream
& endlub( SvStream
& rStrm
)
1445 if ( rStrm
.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE
)
1446 return endlu( rStrm
);
1448 return endl( rStrm
);
1451 SvMemoryStream::SvMemoryStream( void* pBuffer
, std::size_t bufSize
,
1454 if( eMode
& StreamMode::WRITE
)
1455 m_isWritable
= true;
1457 m_isWritable
= false;
1458 nEndOfData
= bufSize
;
1460 pBuf
= static_cast<sal_uInt8
*>(pBuffer
);
1467 SvMemoryStream::SvMemoryStream( std::size_t nInitSize
, std::size_t nResizeOffset
)
1469 m_isWritable
= true;
1472 nResize
= nResizeOffset
;
1475 if( nResize
!= 0 && nResize
< 16 )
1478 AllocateMemory( nInitSize
);
1480 SetBufferSize( 64 );
1483 SvMemoryStream::~SvMemoryStream()
1494 void SvMemoryStream::SetBuffer( void* pNewBuf
, std::size_t nCount
,
1497 SetBufferSize( 0 ); // Init buffering in the base class
1499 if( bOwnsData
&& pNewBuf
!= pBuf
)
1502 pBuf
= static_cast<sal_uInt8
*>(pNewBuf
);
1515 std::size_t SvMemoryStream::GetData( void* pData
, std::size_t nCount
)
1517 std::size_t nMaxCount
= nEndOfData
-nPos
;
1518 if( nCount
> nMaxCount
)
1522 memcpy( pData
, pBuf
+nPos
, nCount
);
1528 std::size_t SvMemoryStream::PutData( const void* pData
, std::size_t nCount
)
1533 std::size_t nMaxCount
= nSize
-nPos
;
1535 // check for overflow
1536 if( nCount
> nMaxCount
)
1540 // copy as much as possible
1542 SetError( SVSTREAM_OUTOFMEMORY
);
1546 tools::Long nNewResize
;
1547 if( nSize
&& nSize
> nResize
)
1550 nNewResize
= nResize
;
1552 if( (nCount
-nMaxCount
) < nResize
)
1554 // lacking memory is smaller than nResize,
1555 // resize accordingly
1556 if( !ReAllocateMemory( nNewResize
) )
1559 SetError( SVSTREAM_WRITE_ERROR
);
1564 // lacking memory is larger than nResize,
1565 // resize by (nCount-nMaxCount) + resize offset
1566 if( !ReAllocateMemory( nCount
-nMaxCount
+nNewResize
) )
1569 SetError( SVSTREAM_WRITE_ERROR
);
1574 assert(pBuf
&& "Possibly Reallocate failed");
1575 memcpy( pBuf
+nPos
, pData
, nCount
);
1578 if( nPos
> nEndOfData
)
1583 sal_uInt64
SvMemoryStream::SeekPos(sal_uInt64
const nNewPos
)
1585 // nEndOfData: First position in stream not allowed to read from
1586 // nSize: Size of allocated buffer
1588 // check if a truncated STREAM_SEEK_TO_END was passed
1589 assert(nNewPos
!= SAL_MAX_UINT32
);
1590 if( nNewPos
< nEndOfData
)
1592 else if( nNewPos
== STREAM_SEEK_TO_END
)
1596 if( nNewPos
>= nSize
) // Does buffer need extension?
1598 if( nResize
) // Is extension possible?
1600 tools::Long nDiff
= static_cast<tools::Long
>(nNewPos
- nSize
+ 1);
1601 nDiff
+= static_cast<tools::Long
>(nResize
);
1602 ReAllocateMemory( nDiff
);
1604 nEndOfData
= nNewPos
;
1606 else // Extension not possible, set pos to end of data
1608 // SetError( SVSTREAM_OUTOFMEMORY );
1612 else // Expand buffer size
1615 nEndOfData
= nNewPos
;
1621 void SvMemoryStream::FlushData()
1625 void SvMemoryStream::ResetError()
1627 SvStream::ClearError();
1630 void SvMemoryStream::AllocateMemory( std::size_t nNewSize
)
1632 pBuf
= new sal_uInt8
[nNewSize
];
1635 // (using Bozo algorithm)
1636 bool SvMemoryStream::ReAllocateMemory( tools::Long nDiff
)
1638 if (!m_isWritable
|| !bOwnsData
)
1641 bool bRetVal
= false;
1642 tools::Long nTemp
= static_cast<tools::Long
>(nSize
);
1644 std::size_t nNewSize
= static_cast<std::size_t>(nTemp
);
1648 sal_uInt8
* pNewBuf
= new sal_uInt8
[nNewSize
];
1650 bRetVal
= true; // Success!
1651 if( nNewSize
< nSize
) // Are we shrinking?
1653 memcpy( pNewBuf
, pBuf
, nNewSize
);
1654 if( nPos
> nNewSize
)
1656 if( nEndOfData
>= nNewSize
)
1657 nEndOfData
= nNewSize
-1;
1663 memcpy( pNewBuf
, pBuf
, nSize
);
1665 memset(pNewBuf
+ nSize
, 0x00, nNewSize
- nSize
);
1686 void SvMemoryStream::FreeMemory()
1696 void* SvMemoryStream::SwitchBuffer()
1701 Seek( STREAM_SEEK_TO_BEGIN
);
1703 void* pRetVal
= pBuf
;
1711 std::size_t nInitSize
= 512;
1712 AllocateMemory(nInitSize
);
1715 SetBufferSize( 64 );
1719 void SvMemoryStream::SetSize(sal_uInt64
const nNewSize
)
1723 SetError(SVSTREAM_INVALID_HANDLE
);
1727 tools::Long nDiff
= static_cast<tools::Long
>(nNewSize
) - static_cast<tools::Long
>(nSize
);
1728 ReAllocateMemory( nDiff
);
1731 void SvMemoryStream::MakeReadOnly()
1734 m_isWritable
= false;
1739 // Create an OString of nLen bytes from rStream
1740 // coverity[ +taint_sanitize ]
1741 OString
read_uInt8s_ToOString(SvStream
& rStrm
, std::size_t nLen
)
1743 rtl_String
*pStr
= nullptr;
1746 nLen
= std::min
<std::size_t>(nLen
, SAL_MAX_INT32
);
1747 //limit allocation to size of file, but + 1 to set eof state
1748 nLen
= std::min
<sal_uInt64
>(nLen
, rStrm
.remainingSize() + 1);
1749 //alloc a (ref-count 1) rtl_String of the desired length.
1750 //rtl_String's buffer is uninitialized, except for null termination
1751 pStr
= rtl_string_alloc(sal::static_int_cast
<sal_Int32
>(nLen
));
1752 SAL_WARN_IF(!pStr
, "tools.stream", "allocation failed");
1755 std::size_t nWasRead
= rStrm
.ReadBytes(pStr
->buffer
, nLen
);
1756 if (nWasRead
!= nLen
)
1758 //on (typically unlikely) short read set length to what we could
1759 //read, and null terminate. Excess buffer capacity remains of
1760 //course, could create a (true) replacement OString if it matters.
1761 pStr
->length
= sal::static_int_cast
<sal_Int32
>(nWasRead
);
1762 pStr
->buffer
[pStr
->length
] = 0;
1767 //take ownership of buffer and return, otherwise return empty string
1768 return pStr
? OString(pStr
, SAL_NO_ACQUIRE
) : OString();
1771 // Create an OUString of nLen sal_Unicode code units from rStream
1772 // coverity[ +taint_sanitize ]
1773 OUString
read_uInt16s_ToOUString(SvStream
& rStrm
, std::size_t nLen
)
1775 rtl_uString
*pStr
= nullptr;
1778 nLen
= std::min
<std::size_t>(nLen
, SAL_MAX_INT32
);
1779 //limit allocation to size of file, but + 1 to set eof state
1780 nLen
= o3tl::sanitizing_min
<sal_uInt64
>(nLen
, (rStrm
.remainingSize() + 2) / 2);
1781 //alloc a (ref-count 1) rtl_uString of the desired length.
1782 //rtl_String's buffer is uninitialized, except for null termination
1783 pStr
= rtl_uString_alloc(sal::static_int_cast
<sal_Int32
>(nLen
));
1784 SAL_WARN_IF(!pStr
, "tools.stream", "allocation failed");
1787 std::size_t nWasRead
= rStrm
.ReadBytes(pStr
->buffer
, nLen
*2)/2;
1788 if (nWasRead
!= nLen
)
1790 //on (typically unlikely) short read set length to what we could
1791 //read, and null terminate. Excess buffer capacity remains of
1792 //course, could create a (true) replacement OUString if it matters.
1793 pStr
->length
= sal::static_int_cast
<sal_Int32
>(nWasRead
);
1794 pStr
->buffer
[pStr
->length
] = 0;
1796 if (rStrm
.IsEndianSwap())
1798 for (sal_Int32 i
= 0; i
< pStr
->length
; ++i
)
1799 pStr
->buffer
[i
] = OSL_SWAPWORD(pStr
->buffer
[i
]);
1804 // take ownership of buffer and return, otherwise return empty string
1805 // coverity[tainted_data] - unhelpful untrusted loop bound
1806 return pStr
? OUString(pStr
, SAL_NO_ACQUIRE
) : OUString();
1811 template <typename T
, typename O
> T
tmpl_convertLineEnd(const T
&rIn
, LineEnd eLineEnd
)
1813 // Determine linebreaks and compute length
1814 bool bConvert
= false; // Needs conversion
1815 sal_Int32 nStrLen
= rIn
.getLength();
1816 sal_Int32 nLineEndLen
= (eLineEnd
== LINEEND_CRLF
) ? 2 : 1;
1817 sal_Int32 nLen
= 0; // Target length
1818 sal_Int32 i
= 0; // Source counter
1822 // \r or \n causes linebreak
1823 if ( (rIn
[i
] == '\r') || (rIn
[i
] == '\n') )
1825 nLen
= nLen
+ nLineEndLen
;
1827 // If set already, skip expensive test
1830 // Do we need to convert?
1831 if ( ((eLineEnd
!= LINEEND_LF
) && (rIn
[i
] == '\n')) ||
1832 ((eLineEnd
== LINEEND_CRLF
) && (i
+1) < nStrLen
&& (rIn
[i
+1] != '\n')) ||
1833 ((eLineEnd
== LINEEND_LF
) &&
1834 ((rIn
[i
] == '\r') || ((i
+1) < nStrLen
&& rIn
[i
+1] == '\r'))) ||
1835 ((eLineEnd
== LINEEND_CR
) &&
1836 ((rIn
[i
] == '\n') || ((i
+1) < nStrLen
&& rIn
[i
+1] == '\n'))) )
1840 // skip char if \r\n or \n\r
1841 if ( (i
+1) < nStrLen
&& ((rIn
[i
+1] == '\r') || (rIn
[i
+1] == '\n')) &&
1842 (rIn
[i
] != rIn
[i
+1]) )
1853 // convert linebreaks, insert string
1858 // \r or \n causes linebreak
1859 if ( (rIn
[i
] == '\r') || (rIn
[i
] == '\n') )
1861 if ( eLineEnd
== LINEEND_CRLF
)
1863 aNewData
.append('\r');
1864 aNewData
.append('\n');
1868 if ( eLineEnd
== LINEEND_CR
)
1869 aNewData
.append('\r');
1871 aNewData
.append('\n');
1874 if ( (i
+1) < nStrLen
&& ((rIn
[i
+1] == '\r') || (rIn
[i
+1] == '\n')) &&
1875 (rIn
[i
] != rIn
[i
+1]) )
1880 aNewData
.append(rIn
[i
]);
1886 return aNewData
.makeStringAndClear();
1890 OString
convertLineEnd(const OString
&rIn
, LineEnd eLineEnd
)
1892 return tmpl_convertLineEnd
<OString
, OStringBuffer
>(rIn
, eLineEnd
);
1895 OUString
convertLineEnd(const OUString
&rIn
, LineEnd eLineEnd
)
1897 return tmpl_convertLineEnd
<OUString
, OUStringBuffer
>(rIn
, eLineEnd
);
1900 std::size_t write_uInt32_lenPrefixed_uInt16s_FromOUString(SvStream
& rStrm
,
1901 std::u16string_view rStr
)
1903 std::size_t nWritten
= 0;
1904 sal_uInt32 nUnits
= std::min
<std::size_t>(rStr
.size(), std::numeric_limits
<sal_uInt32
>::max());
1905 SAL_WARN_IF(static_cast<std::size_t>(nUnits
) != static_cast<std::size_t>(rStr
.size()),
1907 "string too long for prefix count to fit in output type");
1908 rStrm
.WriteUInt32(nUnits
);
1911 nWritten
+= sizeof(sal_uInt32
);
1912 nWritten
+= write_uInt16s_FromOUString(rStrm
, rStr
, nUnits
);
1917 std::size_t write_uInt16_lenPrefixed_uInt16s_FromOUString(SvStream
& rStrm
,
1918 std::u16string_view rStr
)
1920 std::size_t nWritten
= 0;
1921 sal_uInt16 nUnits
= std::min
<std::size_t>(rStr
.size(), std::numeric_limits
<sal_uInt16
>::max());
1922 SAL_WARN_IF(nUnits
!= rStr
.size(),
1924 "string too long for prefix count to fit in output type");
1925 rStrm
.WriteUInt16(nUnits
);
1928 nWritten
+= sizeof(nUnits
);
1929 nWritten
+= write_uInt16s_FromOUString(rStrm
, rStr
, nUnits
);
1934 std::size_t write_uInt16_lenPrefixed_uInt8s_FromOString(SvStream
& rStrm
,
1935 std::string_view rStr
)
1937 std::size_t nWritten
= 0;
1938 sal_uInt16 nUnits
= std::min
<std::size_t>(rStr
.size(), std::numeric_limits
<sal_uInt16
>::max());
1939 SAL_WARN_IF(static_cast<std::size_t>(nUnits
) != static_cast<std::size_t>(rStr
.size()),
1941 "string too long for sal_uInt16 count to fit in output type");
1942 rStrm
.WriteUInt16( nUnits
);
1945 nWritten
+= sizeof(sal_uInt16
);
1946 nWritten
+= rStrm
.WriteBytes(rStr
.data(), nUnits
);
1951 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */