Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / tools / source / stream / stream.cxx
blobc10dad0457fac36fdab7f7d7c25abdcb6d60a033
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
24 #include <cassert>
25 #include <cstddef>
26 #include <memory>
28 #include <string.h>
29 #include <stdio.h>
31 #include <osl/endian.h>
32 #include <osl/diagnose.h>
33 #include <rtl/strbuf.hxx>
34 #include <rtl/ustrbuf.hxx>
35 #include <sal/log.hxx>
37 #include <comphelper/fileformat.h>
39 static void swapNibbles(unsigned char &c)
41 unsigned char nSwapTmp=c;
42 nSwapTmp <<= 4;
43 c >>= 4;
44 c |= nSwapTmp;
47 #include <tools/debug.hxx>
48 #include <tools/stream.hxx>
49 #include <osl/thread.h>
50 #include <algorithm>
52 // !!! Do not inline if already the operators <<,>> are inline
53 static void SwapUShort( sal_uInt16& r )
54 { r = OSL_SWAPWORD(r); }
55 static void SwapShort( short& r )
56 { r = OSL_SWAPWORD(r); }
57 static void SwapULong( sal_uInt32& r )
58 { r = OSL_SWAPDWORD(r); }
59 static void SwapLongInt( sal_Int32& r )
60 { r = OSL_SWAPDWORD(r); }
62 static void SwapUInt64( sal_uInt64& r )
64 union
66 sal_uInt64 n;
67 sal_uInt32 c[2];
68 } s;
70 s.n = r;
71 s.c[0] ^= s.c[1]; // swap the 32 bit words
72 s.c[1] ^= s.c[0];
73 s.c[0] ^= s.c[1];
74 // swap the bytes in the words
75 s.c[0] = OSL_SWAPDWORD(s.c[0]);
76 s.c[1] = OSL_SWAPDWORD(s.c[1]);
77 r = s.n;
79 static void SwapInt64( sal_Int64& r )
81 union
83 sal_Int64 n;
84 sal_Int32 c[2];
85 } s;
87 s.n = r;
88 s.c[0] ^= s.c[1]; // swap the 32 bit words
89 s.c[1] ^= s.c[0];
90 s.c[0] ^= s.c[1];
91 // swap the bytes in the words
92 s.c[0] = OSL_SWAPDWORD(s.c[0]);
93 s.c[1] = OSL_SWAPDWORD(s.c[1]);
94 r = s.n;
97 #ifdef UNX
98 static void SwapFloat( float& r )
100 union
102 float f;
103 sal_uInt32 c;
104 } s;
106 s.f = r;
107 s.c = OSL_SWAPDWORD( s.c );
108 r = s.f;
111 static void SwapDouble( double& r )
113 if( sizeof(double) != 8 )
115 SAL_WARN( "tools.stream", "Can only swap 8-Byte-doubles" );
117 else
119 union
121 double d;
122 sal_uInt32 c[2];
123 } s;
125 s.d = r;
126 s.c[0] ^= s.c[1]; // swap 32-bit values in situ
127 s.c[1] ^= s.c[0];
128 s.c[0] ^= s.c[1];
129 s.c[0] = OSL_SWAPDWORD(s.c[0]); // swap dword itself in situ
130 s.c[1] = OSL_SWAPDWORD(s.c[1]);
131 r = s.d;
134 #endif
136 static void SwapUnicode(sal_Unicode & r) { r = OSL_SWAPWORD(r); }
138 //SDO
140 void SvStream::readNumberWithoutSwap_(void * pDataDest, int nDataSize)
142 if (m_isIoRead && nDataSize <= m_nBufFree)
144 for (int i = 0; i < nDataSize; i++)
145 static_cast<char*>(pDataDest)[i] = m_pBufPos[i];
146 m_nBufActualPos += nDataSize;
147 m_pBufPos += nDataSize;
148 m_nBufFree -= nDataSize;
150 else
152 ReadBytes( pDataDest, nDataSize );
157 void SvStream::writeNumberWithoutSwap_(const void * pDataSrc, int nDataSize)
159 if (m_isIoWrite && nDataSize <= m_nBufFree)
161 for (int i = 0; i < nDataSize; i++)
162 m_pBufPos[i] = static_cast<const char*>(pDataSrc)[i];
163 m_nBufFree -= nDataSize;
164 m_nBufActualPos += nDataSize;
165 if (m_nBufActualPos > m_nBufActualLen)
166 m_nBufActualLen = m_nBufActualPos;
167 m_pBufPos += nDataSize;
168 m_isDirty = true;
170 else
172 WriteBytes( pDataSrc, nDataSize );
176 // class SvLockBytes
178 void SvLockBytes::close()
180 if (m_bOwner)
181 delete m_pStream;
182 m_pStream = nullptr;
186 // virtual
187 ErrCode SvLockBytes::ReadAt(sal_uInt64 const nPos, void * pBuffer, std::size_t nCount,
188 std::size_t * pRead) const
190 if (!m_pStream)
192 OSL_FAIL("SvLockBytes::ReadAt(): Bad stream");
193 return ERRCODE_NONE;
196 m_pStream->Seek(nPos);
197 std::size_t nTheRead = m_pStream->ReadBytes(pBuffer, nCount);
198 if (pRead)
199 *pRead = nTheRead;
200 return m_pStream->GetErrorCode();
203 // virtual
204 ErrCode SvLockBytes::WriteAt(sal_uInt64 const nPos, const void * pBuffer, std::size_t nCount,
205 std::size_t * pWritten)
207 if (!m_pStream)
209 OSL_FAIL("SvLockBytes::WriteAt(): Bad stream");
210 return ERRCODE_NONE;
213 m_pStream->Seek(nPos);
214 std::size_t nTheWritten = m_pStream->WriteBytes(pBuffer, nCount);
215 if (pWritten)
216 *pWritten = nTheWritten;
217 return m_pStream->GetErrorCode();
220 // virtual
221 ErrCode SvLockBytes::Flush() const
223 if (!m_pStream)
225 OSL_FAIL("SvLockBytes::Flush(): Bad stream");
226 return ERRCODE_NONE;
229 m_pStream->Flush();
230 return m_pStream->GetErrorCode();
233 // virtual
234 ErrCode SvLockBytes::SetSize(sal_uInt64 const nSize)
236 if (!m_pStream)
238 OSL_FAIL("SvLockBytes::SetSize(): Bad stream");
239 return ERRCODE_NONE;
242 m_pStream->SetStreamSize(nSize);
243 return m_pStream->GetErrorCode();
246 ErrCode SvLockBytes::Stat(SvLockBytesStat * pStat) const
248 if (!m_pStream)
250 OSL_FAIL("SvLockBytes::Stat(): Bad stream");
251 return ERRCODE_NONE;
254 if (pStat)
256 sal_uInt64 const nPos = m_pStream->Tell();
257 pStat->nSize = m_pStream->Seek(STREAM_SEEK_TO_END);
258 m_pStream->Seek(nPos);
260 return ERRCODE_NONE;
263 // class SvStream
265 std::size_t SvStream::GetData( void* pData, std::size_t nSize )
267 if( !GetError() )
269 DBG_ASSERT( m_xLockBytes.is(), "pure virtual function" );
270 std::size_t nRet(0);
271 m_nError = m_xLockBytes->ReadAt(m_nActPos, pData, nSize, &nRet);
272 m_nActPos += nRet;
273 return nRet;
275 else return 0;
278 std::size_t SvStream::PutData( const void* pData, std::size_t nSize )
280 if( !GetError() )
282 DBG_ASSERT( m_xLockBytes.is(), "pure virtual function" );
283 std::size_t nRet(0);
284 m_nError = m_xLockBytes->WriteAt(m_nActPos, pData, nSize, &nRet);
285 m_nActPos += nRet;
286 return nRet;
288 else return 0;
291 sal_uInt64 SvStream::SeekPos(sal_uInt64 const nPos)
293 // check if a truncated STREAM_SEEK_TO_END was passed
294 assert(nPos != SAL_MAX_UINT32);
295 if( !GetError() && nPos == STREAM_SEEK_TO_END )
297 DBG_ASSERT( m_xLockBytes.is(), "pure virtual function" );
298 SvLockBytesStat aStat;
299 m_xLockBytes->Stat( &aStat );
300 m_nActPos = aStat.nSize;
302 else
303 m_nActPos = nPos;
304 return m_nActPos;
307 void SvStream::FlushData()
309 if( !GetError() )
311 DBG_ASSERT( m_xLockBytes.is(), "pure virtual function" );
312 m_nError = m_xLockBytes->Flush();
316 void SvStream::SetSize(sal_uInt64 const nSize)
318 DBG_ASSERT( m_xLockBytes.is(), "pure virtual function" );
319 m_nError = m_xLockBytes->SetSize( nSize );
322 SvStream::SvStream() :
323 m_nActPos(0)
325 , m_pBufPos(nullptr)
326 , m_nBufSize(0)
327 , m_nBufActualLen(0)
328 , m_nBufActualPos(0)
329 , m_nBufFree(0)
330 , m_isIoRead(false)
331 , m_isIoWrite(false)
333 , m_isDirty(false)
334 , m_isEof(false)
336 , m_nCompressMode(SvStreamCompressFlags::NONE)
337 #if defined UNX
338 , m_eLineDelimiter(LINEEND_LF) // UNIX-Format
339 #else
340 , m_eLineDelimiter(LINEEND_CRLF) // DOS-Format
341 #endif
342 , m_eStreamCharSet(osl_getThreadTextEncoding())
344 , m_nCryptMask(0)
346 , m_nVersion(0)
348 , m_nBufFilePos(0)
349 , m_eStreamMode(StreamMode::NONE)
350 , m_isWritable(true)
353 SetEndian( SvStreamEndian::LITTLE );
355 ClearError();
358 SvStream::SvStream( SvLockBytes* pLockBytesP ) : SvStream()
360 m_xLockBytes = pLockBytesP;
361 if( pLockBytesP ) {
362 const SvStream* pStrm = pLockBytesP->GetStream();
363 if( pStrm ) {
364 SetError( pStrm->GetErrorCode() );
367 SetBufferSize( 256 );
370 SvStream::~SvStream()
372 if (m_xLockBytes.is())
373 Flush();
376 void SvStream::ClearError()
378 m_isEof = false;
379 m_nError = ERRCODE_NONE;
382 void SvStream::SetError( ErrCode nErrorCode )
384 if (m_nError == ERRCODE_NONE)
385 m_nError = nErrorCode;
388 void SvStream::SetEndian( SvStreamEndian nNewFormat )
390 m_nEndian = nNewFormat;
391 m_isSwap = false;
392 #ifdef OSL_BIGENDIAN
393 if (m_nEndian == SvStreamEndian::LITTLE)
394 m_isSwap = true;
395 #else
396 if (m_nEndian == SvStreamEndian::BIG)
397 m_isSwap = true;
398 #endif
401 void SvStream::SetBufferSize( sal_uInt16 nBufferSize )
403 sal_uInt64 const nActualFilePos = Tell();
404 bool bDontSeek = (m_pRWBuf == nullptr);
406 if (m_isDirty && m_isWritable) // due to Windows NT: Access denied
407 Flush();
409 if (m_nBufSize)
411 m_pRWBuf.reset();
412 m_nBufFilePos += m_nBufActualPos;
415 m_pRWBuf = nullptr;
416 m_nBufActualLen = 0;
417 m_nBufActualPos = 0;
418 m_nBufSize = nBufferSize;
419 if (m_nBufSize)
420 m_pRWBuf.reset(new sal_uInt8[ m_nBufSize ]);
421 m_pBufPos = m_pRWBuf.get();
422 m_isIoRead = m_isIoWrite = false;
423 if( !bDontSeek )
424 SeekPos( nActualFilePos );
427 void SvStream::ClearBuffer()
429 m_nBufActualLen = 0;
430 m_nBufActualPos = 0;
431 m_nBufFilePos = 0;
432 m_pBufPos = m_pRWBuf.get();
433 m_isDirty = false;
434 m_isIoRead = m_isIoWrite = false;
436 m_isEof = false;
439 void SvStream::ResetError()
441 ClearError();
444 bool SvStream::ReadByteStringLine( OUString& rStr, rtl_TextEncoding eSrcCharSet,
445 sal_Int32 nMaxBytesToRead )
447 OString aStr;
448 bool bRet = ReadLine( aStr, nMaxBytesToRead);
449 rStr = OStringToOUString(aStr, eSrcCharSet);
450 return bRet;
453 bool SvStream::ReadLine( OString& rStr, sal_Int32 nMaxBytesToRead )
455 sal_Char buf[256+1];
456 bool bEnd = false;
457 sal_uInt64 nOldFilePos = Tell();
458 sal_Char c = 0;
459 std::size_t nTotalLen = 0;
461 OStringBuffer aBuf(4096);
462 while( !bEnd && !GetError() ) // Don't test for EOF as we
463 // are reading block-wise!
465 sal_uInt16 nLen = static_cast<sal_uInt16>(ReadBytes(buf, sizeof(buf)-1));
466 if ( !nLen )
468 if ( aBuf.isEmpty() )
470 // Exit on first block-read error
471 m_isEof = true;
472 rStr.clear();
473 return false;
475 else
476 break;
479 sal_uInt16 j, n;
480 for( j = n = 0; j < nLen ; ++j )
482 c = buf[j];
483 if ( c == '\n' || c == '\r' )
485 bEnd = true;
486 break;
488 if ( n < j )
489 buf[n] = c;
490 ++n;
492 nTotalLen += j;
493 if (nTotalLen > static_cast<std::size_t>(nMaxBytesToRead))
495 n -= nTotalLen - nMaxBytesToRead;
496 nTotalLen = nMaxBytesToRead;
497 bEnd = true;
499 if ( n )
500 aBuf.append(buf, n);
503 if ( !bEnd && !GetError() && !aBuf.isEmpty() )
504 bEnd = true;
506 nOldFilePos += nTotalLen;
507 if( Tell() > nOldFilePos )
508 nOldFilePos++;
509 Seek( nOldFilePos ); // Seek pointer due to BlockRead above
511 if ( bEnd && (c=='\r' || c=='\n') ) // Special treatment for DOS files
513 char cTemp;
514 std::size_t nLen = ReadBytes(&cTemp, sizeof(cTemp));
515 if ( nLen ) {
516 if( cTemp == c || (cTemp != '\n' && cTemp != '\r') )
517 Seek( nOldFilePos );
521 if ( bEnd )
522 m_isEof = false;
523 rStr = aBuf.makeStringAndClear();
524 return bEnd;
527 bool SvStream::ReadUniStringLine( OUString& rStr, sal_Int32 nMaxCodepointsToRead )
529 sal_Unicode buf[256+1];
530 bool bEnd = false;
531 sal_uInt64 nOldFilePos = Tell();
532 sal_Unicode c = 0;
533 std::size_t nTotalLen = 0;
535 DBG_ASSERT( sizeof(sal_Unicode) == sizeof(sal_uInt16), "ReadUniStringLine: swapping sizeof(sal_Unicode) not implemented" );
537 OUStringBuffer aBuf(4096);
538 while( !bEnd && !GetError() ) // Don't test for EOF as we
539 // are reading block-wise!
541 sal_uInt16 nLen = static_cast<sal_uInt16>(ReadBytes( buf, sizeof(buf)-sizeof(sal_Unicode)));
542 nLen /= sizeof(sal_Unicode);
543 if ( !nLen )
545 if ( aBuf.isEmpty() )
547 // exit on first BlockRead error
548 m_isEof = true;
549 rStr.clear();
550 return false;
552 else
553 break;
556 sal_uInt16 j, n;
557 for( j = n = 0; j < nLen ; ++j )
559 if (m_isSwap)
560 SwapUnicode( buf[n] );
561 c = buf[j];
562 if ( c == '\n' || c == '\r' )
564 bEnd = true;
565 break;
567 // erAck 26.02.01: Old behavior was no special treatment of '\0'
568 // character here, but a following rStr+=c did ignore it. Is this
569 // really intended? Or should a '\0' better terminate a line?
570 // The nOldFilePos stuff wasn't correct then anyways.
571 if ( c )
573 if ( n < j )
574 buf[n] = c;
575 ++n;
578 nTotalLen += j;
579 if (nTotalLen > static_cast<std::size_t>(nMaxCodepointsToRead))
581 n -= nTotalLen - nMaxCodepointsToRead;
582 nTotalLen = nMaxCodepointsToRead;
583 bEnd = true;
585 if ( n )
586 aBuf.append( buf, n );
589 if ( !bEnd && !GetError() && !aBuf.isEmpty() )
590 bEnd = true;
592 nOldFilePos += nTotalLen * sizeof(sal_Unicode);
593 if( Tell() > nOldFilePos )
594 nOldFilePos += sizeof(sal_Unicode);
595 Seek( nOldFilePos ); // seek due to BlockRead above
597 if ( bEnd && (c=='\r' || c=='\n') ) // special treatment for DOS files
599 sal_Unicode cTemp;
600 ReadBytes( &cTemp, sizeof(cTemp) );
601 if (m_isSwap)
602 SwapUnicode( cTemp );
603 if( cTemp == c || (cTemp != '\n' && cTemp != '\r') )
604 Seek( nOldFilePos );
607 if ( bEnd )
608 m_isEof = false;
609 rStr = aBuf.makeStringAndClear();
610 return bEnd;
613 bool SvStream::ReadUniOrByteStringLine( OUString& rStr, rtl_TextEncoding eSrcCharSet,
614 sal_Int32 nMaxCodepointsToRead )
616 if ( eSrcCharSet == RTL_TEXTENCODING_UNICODE )
617 return ReadUniStringLine( rStr, nMaxCodepointsToRead );
618 else
619 return ReadByteStringLine( rStr, eSrcCharSet, nMaxCodepointsToRead );
622 OString read_zeroTerminated_uInt8s_ToOString(SvStream& rStream)
624 OStringBuffer aOutput(256);
626 sal_Char buf[ 256 + 1 ];
627 bool bEnd = false;
628 sal_uInt64 nFilePos = rStream.Tell();
630 while( !bEnd && !rStream.GetError() )
632 std::size_t nLen = rStream.ReadBytes(buf, sizeof(buf)-1);
633 if (!nLen)
634 break;
636 std::size_t nReallyRead = nLen;
637 const sal_Char* pPtr = buf;
638 while (nLen && *pPtr)
640 ++pPtr;
641 --nLen;
644 bEnd = ( nReallyRead < sizeof(buf)-1 ) // read less than attempted to read
645 || ( ( nLen > 0 ) // OR it is inside the block we read
646 && ( 0 == *pPtr ) // AND found a string terminator
649 aOutput.append(buf, pPtr - buf);
652 nFilePos += aOutput.getLength();
653 if (rStream.Tell() > nFilePos)
654 rStream.Seek(nFilePos+1); // seek due to FileRead above
655 return aOutput.makeStringAndClear();
658 OUString read_zeroTerminated_uInt8s_ToOUString(SvStream& rStream, rtl_TextEncoding eEnc)
660 return OStringToOUString(
661 read_zeroTerminated_uInt8s_ToOString(rStream), eEnc);
664 /** Attempt to write a prefixed sequence of nUnits 16bit units from an OUString,
665 returned value is number of bytes written */
666 std::size_t write_uInt16s_FromOUString(SvStream& rStrm, const OUString& rStr,
667 std::size_t nUnits)
669 DBG_ASSERT( sizeof(sal_Unicode) == sizeof(sal_uInt16), "write_uInt16s_FromOUString: swapping sizeof(sal_Unicode) not implemented" );
670 std::size_t nWritten;
671 if (!rStrm.IsEndianSwap())
672 nWritten = rStrm.WriteBytes(rStr.getStr(), nUnits * sizeof(sal_Unicode));
673 else
675 std::size_t nLen = nUnits;
676 sal_Unicode aBuf[384];
677 sal_Unicode* const pTmp = ( nLen > 384 ? new sal_Unicode[nLen] : aBuf);
678 memcpy( pTmp, rStr.getStr(), nLen * sizeof(sal_Unicode) );
679 sal_Unicode* p = pTmp;
680 const sal_Unicode* const pStop = pTmp + nLen;
681 while ( p < pStop )
683 SwapUnicode( *p );
684 p++;
686 nWritten = rStrm.WriteBytes( pTmp, nLen * sizeof(sal_Unicode) );
687 if ( pTmp != aBuf )
688 delete [] pTmp;
690 return nWritten;
693 bool SvStream::WriteUnicodeOrByteText( const OUString& rStr, rtl_TextEncoding eDestCharSet )
695 if ( eDestCharSet == RTL_TEXTENCODING_UNICODE )
697 write_uInt16s_FromOUString(*this, rStr, rStr.getLength());
698 return m_nError == ERRCODE_NONE;
700 else
702 OString aStr(OUStringToOString(rStr, eDestCharSet));
703 write_uInt8s_FromOString(*this, aStr, aStr.getLength());
704 return m_nError == ERRCODE_NONE;
708 bool SvStream::WriteByteStringLine( const OUString& rStr, rtl_TextEncoding eDestCharSet )
710 return WriteLine(OUStringToOString(rStr, eDestCharSet));
713 bool SvStream::WriteLine(const OString& rStr)
715 WriteBytes(rStr.getStr(), rStr.getLength());
716 endl(*this);
717 return m_nError == ERRCODE_NONE;
720 bool SvStream::WriteUniOrByteChar( sal_Unicode ch, rtl_TextEncoding eDestCharSet )
722 if ( eDestCharSet == RTL_TEXTENCODING_UNICODE )
723 WriteUnicode(ch);
724 else
726 OString aStr(&ch, 1, eDestCharSet);
727 WriteBytes(aStr.getStr(), aStr.getLength());
729 return m_nError == ERRCODE_NONE;
732 void SvStream::StartWritingUnicodeText()
734 // BOM, Byte Order Mark, U+FEFF, see
735 // http://www.unicode.org/faq/utf_bom.html#BOM
736 // Upon read: 0xfeff(-257) => no swap; 0xfffe(-2) => swap
737 writeNumberWithoutSwap(sal_uInt16(0xfeff)); // write native format
740 void SvStream::StartReadingUnicodeText( rtl_TextEncoding eReadBomCharSet )
742 if (!( eReadBomCharSet == RTL_TEXTENCODING_DONTKNOW ||
743 eReadBomCharSet == RTL_TEXTENCODING_UNICODE ||
744 eReadBomCharSet == RTL_TEXTENCODING_UTF8))
745 return; // nothing to read
747 bool bTryUtf8 = false;
748 sal_uInt16 nFlag(0);
749 sal_sSize nBack = sizeof(nFlag);
750 ReadUInt16( nFlag );
751 switch ( nFlag )
753 case 0xfeff :
754 // native UTF-16
755 if ( eReadBomCharSet == RTL_TEXTENCODING_DONTKNOW ||
756 eReadBomCharSet == RTL_TEXTENCODING_UNICODE)
757 nBack = 0;
758 break;
759 case 0xfffe :
760 // swapped UTF-16
761 if ( eReadBomCharSet == RTL_TEXTENCODING_DONTKNOW ||
762 eReadBomCharSet == RTL_TEXTENCODING_UNICODE)
764 SetEndian( m_nEndian == SvStreamEndian::BIG ? SvStreamEndian::LITTLE : SvStreamEndian::BIG );
765 nBack = 0;
767 break;
768 case 0xefbb :
769 if (m_nEndian == SvStreamEndian::BIG &&
770 (eReadBomCharSet == RTL_TEXTENCODING_DONTKNOW ||
771 eReadBomCharSet == RTL_TEXTENCODING_UTF8))
772 bTryUtf8 = true;
773 break;
774 case 0xbbef :
775 if (m_nEndian == SvStreamEndian::LITTLE &&
776 (eReadBomCharSet == RTL_TEXTENCODING_DONTKNOW ||
777 eReadBomCharSet == RTL_TEXTENCODING_UTF8))
778 bTryUtf8 = true;
779 break;
780 default:
781 ; // nothing
783 if (bTryUtf8)
785 unsigned char nChar(0);
786 nBack += sizeof(nChar);
787 ReadUChar( nChar );
788 if (nChar == 0xbf)
789 nBack = 0; // it is UTF-8
791 if (nBack)
792 SeekRel( -nBack ); // no BOM, pure data
795 sal_uInt64 SvStream::SeekRel(sal_Int64 const nPos)
797 sal_uInt64 nActualPos = Tell();
799 if ( nPos >= 0 )
801 if (SAL_MAX_UINT64 - nActualPos > static_cast<sal_uInt64>(nPos))
802 nActualPos += nPos;
804 else
806 sal_uInt64 const nAbsPos = static_cast<sal_uInt64>(-nPos);
807 if ( nActualPos >= nAbsPos )
808 nActualPos -= nAbsPos;
811 assert((m_pBufPos != nullptr) == bool(m_pRWBuf));
812 if (m_pRWBuf)
814 m_pBufPos = m_pRWBuf.get() + nActualPos;
816 return Seek( nActualPos );
819 SvStream& SvStream::ReadUInt16(sal_uInt16& r)
821 sal_uInt16 n = 0;
822 readNumberWithoutSwap(n);
823 if (good())
825 if (m_isSwap)
826 SwapUShort(n);
827 r = n;
829 return *this;
832 SvStream& SvStream::ReadUInt32(sal_uInt32& r)
834 sal_uInt32 n = 0;
835 readNumberWithoutSwap(n);
836 if (good())
838 if (m_isSwap)
839 SwapULong(n);
840 r = n;
842 return *this;
845 SvStream& SvStream::ReadUInt64(sal_uInt64& r)
847 sal_uInt64 n = 0;
848 readNumberWithoutSwap(n);
849 if (good())
851 if (m_isSwap)
852 SwapUInt64(n);
853 r = n;
855 return *this;
858 SvStream& SvStream::ReadInt16(sal_Int16& r)
860 sal_Int16 n = 0;
861 readNumberWithoutSwap(n);
862 if (good())
864 if (m_isSwap)
865 SwapShort(n);
866 r = n;
868 return *this;
871 SvStream& SvStream::ReadInt32(sal_Int32& r)
873 sal_Int32 n = 0;
874 readNumberWithoutSwap(n);
875 if (good())
877 if (m_isSwap)
878 SwapLongInt(n);
879 r = n;
881 return *this;
884 SvStream& SvStream::ReadInt64(sal_Int64& r)
886 sal_Int64 n = 0;
887 readNumberWithoutSwap(n);
888 if (good())
890 if (m_isSwap)
891 SwapInt64(n);
892 r = n;
894 return *this;
897 SvStream& SvStream::ReadSChar( signed char& r )
899 if (m_isIoRead && sizeof(signed char) <= m_nBufFree)
901 r = *m_pBufPos;
902 m_nBufActualPos += sizeof(signed char);
903 m_pBufPos += sizeof(signed char);
904 m_nBufFree -= sizeof(signed char);
906 else
907 ReadBytes( &r, sizeof(signed char) );
908 return *this;
911 // Special treatment for Chars due to PutBack
913 SvStream& SvStream::ReadChar( char& r )
915 if (m_isIoRead && sizeof(char) <= m_nBufFree)
917 r = *m_pBufPos;
918 m_nBufActualPos += sizeof(char);
919 m_pBufPos += sizeof(char);
920 m_nBufFree -= sizeof(char);
922 else
923 ReadBytes( &r, sizeof(char) );
924 return *this;
927 SvStream& SvStream::ReadUChar( unsigned char& r )
929 if (m_isIoRead && sizeof(char) <= m_nBufFree)
931 r = *m_pBufPos;
932 m_nBufActualPos += sizeof(char);
933 m_pBufPos += sizeof(char);
934 m_nBufFree -= sizeof(char);
936 else
937 ReadBytes( &r, sizeof(char) );
938 return *this;
941 SvStream& SvStream::ReadUtf16(sal_Unicode& r)
943 sal_uInt16 n = 0;
944 readNumberWithoutSwap(n);
945 if (good())
947 if (m_isSwap)
948 SwapUShort(n);
949 r = sal_Unicode(n);
951 return *this;
954 SvStream& SvStream::ReadCharAsBool( bool& r )
956 if (m_isIoRead && sizeof(char) <= m_nBufFree)
958 SAL_WARN_IF(
959 *m_pBufPos > 1, "tools.stream", unsigned(*m_pBufPos) << " not 0/1");
960 r = *m_pBufPos != 0;
961 m_nBufActualPos += sizeof(char);
962 m_pBufPos += sizeof(char);
963 m_nBufFree -= sizeof(char);
965 else
967 unsigned char c;
968 if (ReadBytes(&c, 1) == 1)
970 SAL_WARN_IF(c > 1, "tools.stream", unsigned(c) << " not 0/1");
971 r = c != 0;
974 return *this;
977 SvStream& SvStream::ReadFloat(float& r)
979 float n = 0;
980 readNumberWithoutSwap(n);
981 if (good())
983 #if defined UNX
984 if (m_isSwap)
985 SwapFloat(n);
986 #endif
987 r = n;
989 return *this;
992 SvStream& SvStream::ReadDouble(double& r)
994 double n = 0;
995 readNumberWithoutSwap(n);
996 if (good())
998 #if defined UNX
999 if (m_isSwap)
1000 SwapDouble(n);
1001 #endif
1002 r = n;
1004 return *this;
1007 SvStream& SvStream::ReadStream( SvStream& rStream )
1009 const sal_uInt32 cBufLen = 0x8000;
1010 std::unique_ptr<char[]> pBuf( new char[ cBufLen ] );
1012 sal_uInt32 nCount;
1013 do {
1014 nCount = ReadBytes( pBuf.get(), cBufLen );
1015 rStream.WriteBytes( pBuf.get(), nCount );
1016 } while( nCount == cBufLen );
1018 return *this;
1021 SvStream& SvStream::WriteUInt16( sal_uInt16 v )
1023 if (m_isSwap)
1024 SwapUShort(v);
1025 writeNumberWithoutSwap(v);
1026 return *this;
1029 SvStream& SvStream::WriteUInt32( sal_uInt32 v )
1031 if (m_isSwap)
1032 SwapULong(v);
1033 writeNumberWithoutSwap(v);
1034 return *this;
1037 SvStream& SvStream::WriteUInt64( sal_uInt64 v )
1039 if (m_isSwap)
1040 SwapUInt64(v);
1041 writeNumberWithoutSwap(v);
1042 return *this;
1045 SvStream& SvStream::WriteInt16( sal_Int16 v )
1047 if (m_isSwap)
1048 SwapShort(v);
1049 writeNumberWithoutSwap(v);
1050 return *this;
1053 SvStream& SvStream::WriteInt32( sal_Int32 v )
1055 if (m_isSwap)
1056 SwapLongInt(v);
1057 writeNumberWithoutSwap(v);
1058 return *this;
1061 SvStream& SvStream::WriteInt64 (sal_Int64 v)
1063 if (m_isSwap)
1064 SwapInt64(v);
1065 writeNumberWithoutSwap(v);
1066 return *this;
1069 SvStream& SvStream::WriteSChar( signed char v )
1071 //SDO
1072 if (m_isIoWrite && sizeof(signed char) <= m_nBufFree)
1074 *m_pBufPos = v;
1075 m_pBufPos++; // sizeof(char);
1076 m_nBufActualPos++;
1077 if (m_nBufActualPos > m_nBufActualLen) // Append ?
1078 m_nBufActualLen = m_nBufActualPos;
1079 m_nBufFree--; // = sizeof(char);
1080 m_isDirty = true;
1082 else
1083 WriteBytes( &v, sizeof(signed char) );
1084 return *this;
1087 // Special treatment for Chars due to PutBack
1089 SvStream& SvStream::WriteChar( char v )
1091 //SDO
1092 if (m_isIoWrite && sizeof(char) <= m_nBufFree)
1094 *m_pBufPos = v;
1095 m_pBufPos++; // sizeof(char);
1096 m_nBufActualPos++;
1097 if (m_nBufActualPos > m_nBufActualLen) // Append ?
1098 m_nBufActualLen = m_nBufActualPos;
1099 m_nBufFree--; // = sizeof(char);
1100 m_isDirty = true;
1102 else
1103 WriteBytes( &v, sizeof(char) );
1104 return *this;
1107 SvStream& SvStream::WriteUChar( unsigned char v )
1109 //SDO
1110 if (m_isIoWrite && sizeof(char) <= m_nBufFree)
1112 *reinterpret_cast<unsigned char*>(m_pBufPos) = v;
1113 m_pBufPos++; // = sizeof(char);
1114 m_nBufActualPos++; // = sizeof(char);
1115 if (m_nBufActualPos > m_nBufActualLen) // Append ?
1116 m_nBufActualLen = m_nBufActualPos;
1117 m_nBufFree--;
1118 m_isDirty = true;
1120 else
1121 WriteBytes( &v, sizeof(char) );
1122 return *this;
1125 SvStream& SvStream::WriteUInt8( sal_uInt8 v )
1127 return WriteUChar(v);
1130 SvStream& SvStream::WriteUnicode( sal_Unicode v )
1132 return WriteUInt16(v);
1135 SvStream& SvStream::WriteFloat( float v )
1137 #ifdef UNX
1138 if (m_isSwap)
1139 SwapFloat(v);
1140 #endif
1141 writeNumberWithoutSwap(v);
1142 return *this;
1145 SvStream& SvStream::WriteDouble ( const double& r )
1147 #if defined UNX
1148 if (m_isSwap)
1150 double nHelp = r;
1151 SwapDouble(nHelp);
1152 writeNumberWithoutSwap(nHelp);
1153 return *this;
1155 else
1156 #endif
1158 writeNumberWithoutSwap(r);
1160 return *this;
1163 SvStream& SvStream::WriteCharPtr( const char* pBuf )
1165 WriteBytes( pBuf, strlen(pBuf) );
1166 return *this;
1169 SvStream& SvStream::WriteStream( SvStream& rStream )
1171 const sal_uInt32 cBufLen = 0x8000;
1172 std::unique_ptr<char[]> pBuf( new char[ cBufLen ] );
1173 sal_uInt32 nCount;
1174 do {
1175 nCount = rStream.ReadBytes( pBuf.get(), cBufLen );
1176 WriteBytes( pBuf.get(), nCount );
1177 } while( nCount == cBufLen );
1179 return *this;
1182 sal_uInt64 SvStream::WriteStream( SvStream& rStream, sal_uInt64 nSize )
1184 const sal_uInt32 cBufLen = 0x8000;
1185 std::unique_ptr<char[]> pBuf( new char[ cBufLen ] );
1186 sal_uInt32 nCurBufLen = cBufLen;
1187 sal_uInt32 nCount;
1188 sal_uInt64 nWriteSize = nSize;
1192 nCurBufLen = std::min<sal_uInt64>(nCurBufLen, nWriteSize);
1193 nCount = rStream.ReadBytes(pBuf.get(), nCurBufLen);
1194 WriteBytes( pBuf.get(), nCount );
1195 nWriteSize -= nCount;
1197 while( nWriteSize && nCount == nCurBufLen );
1199 return nSize - nWriteSize;
1202 OUString SvStream::ReadUniOrByteString( rtl_TextEncoding eSrcCharSet )
1204 // read UTF-16 string directly from stream ?
1205 if (eSrcCharSet == RTL_TEXTENCODING_UNICODE)
1206 return read_uInt32_lenPrefixed_uInt16s_ToOUString(*this);
1207 return read_uInt16_lenPrefixed_uInt8s_ToOUString(*this, eSrcCharSet);
1210 SvStream& SvStream::WriteUniOrByteString( const OUString& rStr, rtl_TextEncoding eDestCharSet )
1212 // write UTF-16 string directly into stream ?
1213 if (eDestCharSet == RTL_TEXTENCODING_UNICODE)
1214 write_uInt32_lenPrefixed_uInt16s_FromOUString(*this, rStr);
1215 else
1216 write_uInt16_lenPrefixed_uInt8s_FromOUString(*this, rStr, eDestCharSet);
1217 return *this;
1220 void SvStream::FlushBuffer()
1222 if (m_isDirty) // Does stream require a flush?
1224 SeekPos(m_nBufFilePos);
1225 if (m_nCryptMask)
1226 CryptAndWriteBuffer(m_pRWBuf.get(), m_nBufActualLen);
1227 else if (PutData(m_pRWBuf.get(), m_nBufActualLen) != m_nBufActualLen)
1228 SetError(SVSTREAM_WRITE_ERROR);
1229 m_isDirty = false;
1233 std::size_t SvStream::ReadBytes( void* pData, std::size_t nCount )
1235 std::size_t nSaveCount = nCount;
1237 if (!m_pRWBuf)
1239 nCount = GetData( pData,nCount);
1240 if (m_nCryptMask)
1241 EncryptBuffer(pData, nCount);
1242 m_nBufFilePos += nCount;
1244 else
1246 // check if block is completely within buffer
1247 m_isIoRead = true;
1248 m_isIoWrite = false;
1249 if (nCount <= static_cast<std::size_t>(m_nBufActualLen - m_nBufActualPos))
1251 // => yes
1252 if (nCount != 0)
1253 memcpy(pData, m_pBufPos, static_cast<size_t>(nCount));
1254 m_nBufActualPos = m_nBufActualPos + static_cast<sal_uInt16>(nCount);
1255 m_pBufPos += nCount;
1256 m_nBufFree = m_nBufFree - static_cast<sal_uInt16>(nCount);
1258 else
1260 FlushBuffer();
1262 // Does data block fit into buffer?
1263 if (nCount > m_nBufSize)
1265 // => No! Thus read directly
1266 // into target area without using the buffer
1268 m_isIoRead = false;
1270 SeekPos(m_nBufFilePos + m_nBufActualPos);
1271 m_nBufActualLen = 0;
1272 m_pBufPos = m_pRWBuf.get();
1273 nCount = GetData( pData, nCount );
1274 if (m_nCryptMask)
1275 EncryptBuffer(pData, nCount);
1276 m_nBufFilePos += nCount;
1277 m_nBufFilePos += m_nBufActualPos;
1278 m_nBufActualPos = 0;
1280 else
1282 // => Yes. Fill buffer first, then copy to target area
1284 m_nBufFilePos += m_nBufActualPos;
1285 SeekPos(m_nBufFilePos);
1287 // TODO: Typecast before GetData, sal_uInt16 nCountTmp
1288 std::size_t nCountTmp = GetData( m_pRWBuf.get(), m_nBufSize );
1289 if (m_nCryptMask)
1290 EncryptBuffer(m_pRWBuf.get(), nCountTmp);
1291 m_nBufActualLen = static_cast<sal_uInt16>(nCountTmp);
1292 if( nCount > nCountTmp )
1294 nCount = nCountTmp; // trim count back, EOF see below
1296 memcpy( pData, m_pRWBuf.get(), static_cast<size_t>(nCount) );
1297 m_nBufActualPos = static_cast<sal_uInt16>(nCount);
1298 m_pBufPos = m_pRWBuf.get() + nCount;
1302 m_isEof = false;
1303 m_nBufFree = m_nBufActualLen - m_nBufActualPos;
1304 if (nCount != nSaveCount && m_nError != ERRCODE_IO_PENDING)
1305 m_isEof = true;
1306 if (nCount == nSaveCount && m_nError == ERRCODE_IO_PENDING)
1307 m_nError = ERRCODE_NONE;
1308 return nCount;
1311 std::size_t SvStream::WriteBytes( const void* pData, std::size_t nCount )
1313 if( !nCount )
1314 return 0;
1316 if (!m_isWritable)
1318 SetError( ERRCODE_IO_CANTWRITE );
1319 return 0;
1322 if (!m_pRWBuf)
1324 if (m_nCryptMask)
1325 nCount = CryptAndWriteBuffer( pData, nCount );
1326 else
1327 nCount = PutData( pData, nCount );
1328 m_nBufFilePos += nCount;
1329 return nCount;
1332 m_isIoRead = false;
1333 m_isIoWrite = true;
1334 if (nCount <= static_cast<std::size_t>(m_nBufSize - m_nBufActualPos))
1336 memcpy( m_pBufPos, pData, static_cast<size_t>(nCount) );
1337 m_nBufActualPos = m_nBufActualPos + static_cast<sal_uInt16>(nCount);
1338 // Update length if buffer was updated
1339 if (m_nBufActualPos > m_nBufActualLen)
1340 m_nBufActualLen = m_nBufActualPos;
1342 m_pBufPos += nCount;
1343 m_isDirty = true;
1345 else
1347 FlushBuffer();
1349 // Does data block fit into buffer?
1350 if (nCount > m_nBufSize)
1352 m_isIoWrite = false;
1353 m_nBufFilePos += m_nBufActualPos;
1354 m_nBufActualLen = 0;
1355 m_nBufActualPos = 0;
1356 m_pBufPos = m_pRWBuf.get();
1357 SeekPos(m_nBufFilePos);
1358 if (m_nCryptMask)
1359 nCount = CryptAndWriteBuffer( pData, nCount );
1360 else
1361 nCount = PutData( pData, nCount );
1362 m_nBufFilePos += nCount;
1364 else
1366 // Copy block to buffer
1367 memcpy( m_pRWBuf.get(), pData, static_cast<size_t>(nCount) );
1369 // Mind the order!
1370 m_nBufFilePos += m_nBufActualPos;
1371 m_nBufActualPos = static_cast<sal_uInt16>(nCount);
1372 m_pBufPos = m_pRWBuf.get() + nCount;
1373 m_nBufActualLen = static_cast<sal_uInt16>(nCount);
1374 m_isDirty = true;
1377 m_nBufFree = m_nBufSize - m_nBufActualPos;
1378 return nCount;
1381 sal_uInt64 SvStream::Seek(sal_uInt64 const nFilePos)
1383 m_isIoRead = m_isIoWrite = false;
1384 m_isEof = false;
1385 if (!m_pRWBuf)
1387 m_nBufFilePos = SeekPos( nFilePos );
1388 DBG_ASSERT(Tell() == m_nBufFilePos,"Out Of Sync!");
1389 return m_nBufFilePos;
1392 // Is seek position within buffer?
1393 if (nFilePos >= m_nBufFilePos && nFilePos <= (m_nBufFilePos + m_nBufActualLen))
1395 m_nBufActualPos = static_cast<sal_uInt16>(nFilePos - m_nBufFilePos);
1396 m_pBufPos = m_pRWBuf.get() + m_nBufActualPos;
1397 // Update m_nBufFree to avoid crash upon PutBack
1398 m_nBufFree = m_nBufActualLen - m_nBufActualPos;
1400 else
1402 FlushBuffer();
1403 m_nBufActualLen = 0;
1404 m_nBufActualPos = 0;
1405 m_pBufPos = m_pRWBuf.get();
1406 m_nBufFilePos = SeekPos( nFilePos );
1408 return m_nBufFilePos + m_nBufActualPos;
1411 bool checkSeek(SvStream &rSt, sal_uInt64 nOffset)
1413 const sal_uInt64 nMaxSeek(rSt.Tell() + rSt.remainingSize());
1414 return (nOffset <= nMaxSeek && rSt.Seek(nOffset) == nOffset);
1417 //STREAM_SEEK_TO_END in some of the Seek backends is special cased to be
1418 //efficient, in others e.g. SotStorageStream it's really horribly slow, and in
1419 //those this should be overridden
1420 sal_uInt64 SvStream::remainingSize()
1422 sal_uInt64 const nCurr = Tell();
1423 sal_uInt64 const nEnd = TellEnd();
1424 sal_uInt64 nMaxAvailable = nEnd > nCurr ? (nEnd-nCurr) : 0;
1425 Seek(nCurr);
1426 return nMaxAvailable;
1429 sal_uInt64 SvStream::TellEnd()
1431 FlushBuffer();
1432 sal_uInt64 const nCurr = Tell();
1433 sal_uInt64 const nEnd = Seek(STREAM_SEEK_TO_END);
1434 Seek(nCurr);
1435 return nEnd;
1438 void SvStream::Flush()
1440 FlushBuffer();
1441 if (m_isWritable)
1442 FlushData();
1445 void SvStream::RefreshBuffer()
1447 FlushBuffer();
1448 SeekPos(m_nBufFilePos);
1449 m_nBufActualLen = static_cast<sal_uInt16>(GetData( m_pRWBuf.get(), m_nBufSize ));
1450 if (m_nBufActualLen && m_nError == ERRCODE_IO_PENDING)
1451 m_nError = ERRCODE_NONE;
1452 if (m_nCryptMask)
1453 EncryptBuffer(m_pRWBuf.get(), static_cast<std::size_t>(m_nBufActualLen));
1454 m_isIoRead = m_isIoWrite = false;
1457 SvStream& SvStream::WriteInt32AsString(sal_Int32 nInt32)
1459 char buffer[12];
1460 std::size_t nLen = sprintf(buffer, "%" SAL_PRIdINT32, nInt32);
1461 WriteBytes(buffer, nLen);
1462 return *this;
1465 SvStream& SvStream::WriteUInt32AsString(sal_uInt32 nUInt32)
1467 char buffer[11];
1468 std::size_t nLen = sprintf(buffer, "%" SAL_PRIuUINT32, nUInt32);
1469 WriteBytes(buffer, nLen);
1470 return *this;
1473 #define CRYPT_BUFSIZE 1024
1475 /// Encrypt and write
1476 std::size_t SvStream::CryptAndWriteBuffer( const void* pStart, std::size_t nLen)
1478 unsigned char pTemp[CRYPT_BUFSIZE];
1479 unsigned char const * pDataPtr = static_cast<unsigned char const *>(pStart);
1480 std::size_t nCount = 0;
1481 std::size_t nBufCount;
1482 unsigned char nMask = m_nCryptMask;
1485 if( nLen >= CRYPT_BUFSIZE )
1486 nBufCount = CRYPT_BUFSIZE;
1487 else
1488 nBufCount = nLen;
1489 nLen -= nBufCount;
1490 memcpy( pTemp, pDataPtr, static_cast<sal_uInt16>(nBufCount) );
1491 // ******** Encrypt ********
1492 for (unsigned char & rn : pTemp)
1494 unsigned char aCh = rn;
1495 aCh ^= nMask;
1496 swapNibbles(aCh);
1497 rn = aCh;
1499 // *************************
1500 nCount += PutData( pTemp, nBufCount );
1501 pDataPtr += nBufCount;
1503 while ( nLen );
1504 return nCount;
1507 void SvStream::EncryptBuffer(void* pStart, std::size_t nLen) const
1509 unsigned char* pTemp = static_cast<unsigned char*>(pStart);
1510 unsigned char nMask = m_nCryptMask;
1512 for ( std::size_t n=0; n < nLen; n++, pTemp++ )
1514 unsigned char aCh = *pTemp;
1515 swapNibbles(aCh);
1516 aCh ^= nMask;
1517 *pTemp = aCh;
1521 static unsigned char implGetCryptMask(const sal_Char* pStr, sal_Int32 nLen, long nVersion)
1523 unsigned char nCryptMask = 0;
1525 if (!nLen)
1526 return nCryptMask;
1528 if( nVersion <= SOFFICE_FILEFORMAT_31 )
1530 while( nLen )
1532 nCryptMask ^= *pStr;
1533 pStr++;
1534 nLen--;
1537 else // BugFix #25888#
1539 for( sal_Int32 i = 0; i < nLen; i++ ) {
1540 nCryptMask ^= pStr[i];
1541 if( nCryptMask & 0x80 ) {
1542 nCryptMask <<= 1;
1543 nCryptMask++;
1545 else
1546 nCryptMask <<= 1;
1550 if( !nCryptMask )
1551 nCryptMask = 67;
1553 return nCryptMask;
1556 void SvStream::SetCryptMaskKey(const OString& rCryptMaskKey)
1558 m_aCryptMaskKey = rCryptMaskKey;
1559 m_nCryptMask = implGetCryptMask(m_aCryptMaskKey.getStr(),
1560 m_aCryptMaskKey.getLength(), GetVersion());
1563 bool SvStream::SetStreamSize(sal_uInt64 const nSize)
1565 #ifdef DBG_UTIL
1566 sal_uInt64 nFPos = Tell();
1567 #endif
1568 sal_uInt16 nBuf = m_nBufSize;
1569 SetBufferSize( 0 );
1570 SetSize( nSize );
1571 if (nSize < m_nBufFilePos)
1573 m_nBufFilePos = nSize;
1575 SetBufferSize( nBuf );
1576 #ifdef DBG_UTIL
1577 DBG_ASSERT(Tell()==nFPos,"SetStreamSize failed");
1578 #endif
1579 return (m_nError == ERRCODE_NONE);
1582 SvStream& endl( SvStream& rStr )
1584 LineEnd eDelim = rStr.GetLineDelimiter();
1585 if ( eDelim == LINEEND_CR )
1586 rStr.WriteChar('\r');
1587 else if( eDelim == LINEEND_LF )
1588 rStr.WriteChar('\n');
1589 else
1590 rStr.WriteChar('\r').WriteChar('\n');
1591 return rStr;
1594 SvStream& endlu( SvStream& rStrm )
1596 switch ( rStrm.GetLineDelimiter() )
1598 case LINEEND_CR :
1599 rStrm.WriteUnicode('\r');
1600 break;
1601 case LINEEND_LF :
1602 rStrm.WriteUnicode('\n');
1603 break;
1604 default:
1605 rStrm.WriteUnicode('\r').WriteUnicode('\n');
1607 return rStrm;
1610 SvStream& endlub( SvStream& rStrm )
1612 if ( rStrm.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE )
1613 return endlu( rStrm );
1614 else
1615 return endl( rStrm );
1618 SvMemoryStream::SvMemoryStream( void* pBuffer, std::size_t bufSize,
1619 StreamMode eMode )
1621 if( eMode & StreamMode::WRITE )
1622 m_isWritable = true;
1623 else
1624 m_isWritable = false;
1625 nEndOfData = bufSize;
1626 bOwnsData = false;
1627 pBuf = static_cast<sal_uInt8 *>(pBuffer);
1628 nResize = 0;
1629 nSize = bufSize;
1630 nPos = 0;
1631 SetBufferSize( 0 );
1634 SvMemoryStream::SvMemoryStream( std::size_t nInitSize, std::size_t nResizeOffset )
1636 m_isWritable = true;
1637 bOwnsData = true;
1638 nEndOfData = 0;
1639 nResize = nResizeOffset;
1640 nPos = 0;
1641 pBuf = nullptr;
1642 if( nResize != 0 && nResize < 16 )
1643 nResize = 16;
1644 if( nInitSize )
1645 AllocateMemory( nInitSize );
1646 nSize = nInitSize;
1647 SetBufferSize( 64 );
1650 SvMemoryStream::~SvMemoryStream()
1652 if( pBuf )
1654 if( bOwnsData )
1655 FreeMemory();
1656 else
1657 Flush();
1661 sal_uInt64 SvMemoryStream::GetSize()
1663 Flush();
1664 sal_uInt64 const nTemp = Tell();
1665 sal_uInt64 const nLength = Seek( STREAM_SEEK_TO_END );
1666 Seek( nTemp );
1667 return nLength;
1670 void SvMemoryStream::SetBuffer( void* pNewBuf, std::size_t nCount,
1671 std::size_t nEOF )
1673 SetBufferSize( 0 ); // Init buffering in the base class
1674 Seek( 0 );
1675 if( bOwnsData && pNewBuf != pBuf )
1676 FreeMemory();
1678 pBuf = static_cast<sal_uInt8 *>(pNewBuf);
1679 nPos = 0;
1680 nSize = nCount;
1681 nResize = 0;
1682 bOwnsData = false;
1684 if( nEOF > nCount )
1685 nEOF = nCount;
1686 nEndOfData = nEOF;
1688 ResetError();
1691 std::size_t SvMemoryStream::GetData( void* pData, std::size_t nCount )
1693 std::size_t nMaxCount = nEndOfData-nPos;
1694 if( nCount > nMaxCount )
1695 nCount = nMaxCount;
1696 if (nCount != 0)
1698 memcpy( pData, pBuf+nPos, static_cast<size_t>(nCount) );
1700 nPos += nCount;
1701 return nCount;
1704 std::size_t SvMemoryStream::PutData( const void* pData, std::size_t nCount )
1706 if( GetError() )
1707 return 0L;
1709 std::size_t nMaxCount = nSize-nPos;
1711 // check for overflow
1712 if( nCount > nMaxCount )
1714 if( nResize == 0 )
1716 // copy as much as possible
1717 nCount = nMaxCount;
1718 SetError( SVSTREAM_OUTOFMEMORY );
1720 else
1722 long nNewResize;
1723 if( nSize && nSize > nResize )
1724 nNewResize = nSize;
1725 else
1726 nNewResize = nResize;
1728 if( (nCount-nMaxCount) < nResize )
1730 // lacking memory is smaller than nResize,
1731 // resize accordingly
1732 if( !ReAllocateMemory( nNewResize) )
1734 nCount = 0;
1735 SetError( SVSTREAM_WRITE_ERROR );
1738 else
1740 // lacking memory is larger than nResize,
1741 // resize by (nCount-nMaxCount) + resize offset
1742 if( !ReAllocateMemory( nCount-nMaxCount+nNewResize ) )
1744 nCount = 0;
1745 SetError( SVSTREAM_WRITE_ERROR );
1750 assert(pBuf && "Possibly Reallocate failed");
1751 memcpy( pBuf+nPos, pData, static_cast<size_t>(nCount));
1753 nPos += nCount;
1754 if( nPos > nEndOfData )
1755 nEndOfData = nPos;
1756 return nCount;
1759 sal_uInt64 SvMemoryStream::SeekPos(sal_uInt64 const nNewPos)
1761 // nEndOfData: First position in stream not allowed to read from
1762 // nSize: Size of allocated buffer
1764 // check if a truncated STREAM_SEEK_TO_END was passed
1765 assert(nNewPos != SAL_MAX_UINT32);
1766 if( nNewPos < nEndOfData )
1767 nPos = nNewPos;
1768 else if( nNewPos == STREAM_SEEK_TO_END )
1769 nPos = nEndOfData;
1770 else
1772 if( nNewPos >= nSize ) // Does buffer need extension?
1774 if( nResize ) // Is extension possible?
1776 long nDiff = static_cast<long>(nNewPos - nSize + 1);
1777 nDiff += static_cast<long>(nResize);
1778 ReAllocateMemory( nDiff );
1779 nPos = nNewPos;
1780 nEndOfData = nNewPos;
1782 else // Extension not possible, set pos to end of data
1784 // SetError( SVSTREAM_OUTOFMEMORY );
1785 nPos = nEndOfData;
1788 else // Expand buffer size
1790 nPos = nNewPos;
1791 nEndOfData = nNewPos;
1794 return nPos;
1797 void SvMemoryStream::FlushData()
1801 void SvMemoryStream::ResetError()
1803 SvStream::ClearError();
1806 void SvMemoryStream::AllocateMemory( std::size_t nNewSize )
1808 pBuf = new sal_uInt8[nNewSize];
1811 // (using Bozo algorithm)
1812 bool SvMemoryStream::ReAllocateMemory( long nDiff )
1814 if (!m_isWritable || !bOwnsData)
1815 return false;
1817 bool bRetVal = false;
1818 long nTemp = static_cast<long>(nSize);
1819 nTemp += nDiff;
1820 std::size_t nNewSize = static_cast<std::size_t>(nTemp);
1822 if( nNewSize )
1824 sal_uInt8* pNewBuf = new sal_uInt8[nNewSize];
1826 bRetVal = true; // Success!
1827 if( nNewSize < nSize ) // Are we shrinking?
1829 memcpy( pNewBuf, pBuf, static_cast<size_t>(nNewSize) );
1830 if( nPos > nNewSize )
1831 nPos = 0;
1832 if( nEndOfData >= nNewSize )
1833 nEndOfData = nNewSize-1;
1835 else
1837 if (nSize != 0)
1839 memcpy( pNewBuf, pBuf, static_cast<size_t>(nSize) );
1841 memset(pNewBuf + nSize, 0x00, nNewSize - nSize);
1844 FreeMemory();
1846 pBuf = pNewBuf;
1847 nSize = nNewSize;
1849 else
1851 bRetVal = true;
1852 FreeMemory();
1853 pBuf = nullptr;
1854 nSize = 0;
1855 nEndOfData = 0;
1856 nPos = 0;
1859 return bRetVal;
1862 void SvMemoryStream::FreeMemory()
1864 assert(bOwnsData);
1865 if (bOwnsData)
1867 delete[] pBuf;
1868 pBuf = nullptr;
1872 void* SvMemoryStream::SwitchBuffer()
1874 Flush();
1875 if( !bOwnsData )
1876 return nullptr;
1877 Seek( STREAM_SEEK_TO_BEGIN );
1879 void* pRetVal = pBuf;
1880 pBuf = nullptr;
1881 nEndOfData = 0;
1882 nResize = 64;
1883 nPos = 0;
1885 ResetError();
1887 std::size_t nInitSize = 512;
1888 AllocateMemory(nInitSize);
1889 nSize = nInitSize;
1891 SetBufferSize( 64 );
1892 return pRetVal;
1895 void SvMemoryStream::SetSize(sal_uInt64 const nNewSize)
1897 if (!m_isWritable)
1899 SetError(SVSTREAM_INVALID_HANDLE);
1900 return;
1903 long nDiff = static_cast<long>(nNewSize) - static_cast<long>(nSize);
1904 ReAllocateMemory( nDiff );
1907 //Create an OString of nLen bytes from rStream
1908 OString read_uInt8s_ToOString(SvStream& rStrm, std::size_t nLen)
1910 rtl_String *pStr = nullptr;
1911 if (nLen)
1913 nLen = std::min<std::size_t>(nLen, SAL_MAX_INT32);
1914 //limit allocation to size of file, but + 1 to set eof state
1915 nLen = std::min<sal_uInt64>(nLen, rStrm.remainingSize() + 1);
1916 //alloc a (ref-count 1) rtl_String of the desired length.
1917 //rtl_String's buffer is uninitialized, except for null termination
1918 pStr = rtl_string_alloc(sal::static_int_cast<sal_Int32>(nLen));
1919 SAL_WARN_IF(!pStr, "tools.stream", "allocation failed");
1920 if (pStr)
1922 std::size_t nWasRead = rStrm.ReadBytes(pStr->buffer, nLen);
1923 if (nWasRead != nLen)
1925 //on (typically unlikely) short read set length to what we could
1926 //read, and null terminate. Excess buffer capacity remains of
1927 //course, could create a (true) replacement OString if it matters.
1928 pStr->length = sal::static_int_cast<sal_Int32>(nWasRead);
1929 pStr->buffer[pStr->length] = 0;
1934 //take ownership of buffer and return, otherwise return empty string
1935 return pStr ? OString(pStr, SAL_NO_ACQUIRE) : OString();
1938 //Create an OUString of nLen sal_Unicode code units from rStream
1939 OUString read_uInt16s_ToOUString(SvStream& rStrm, std::size_t nLen)
1941 rtl_uString *pStr = nullptr;
1942 if (nLen)
1944 nLen = std::min<std::size_t>(nLen, SAL_MAX_INT32);
1945 //limit allocation to size of file, but + 1 to set eof state
1946 nLen = std::min<sal_uInt64>(nLen, (rStrm.remainingSize() + 2) / 2);
1947 //alloc a (ref-count 1) rtl_uString of the desired length.
1948 //rtl_String's buffer is uninitialized, except for null termination
1949 pStr = rtl_uString_alloc(sal::static_int_cast<sal_Int32>(nLen));
1950 SAL_WARN_IF(!pStr, "tools.stream", "allocation failed");
1951 if (pStr)
1953 std::size_t nWasRead = rStrm.ReadBytes(pStr->buffer, nLen*2)/2;
1954 if (nWasRead != nLen)
1956 //on (typically unlikely) short read set length to what we could
1957 //read, and null terminate. Excess buffer capacity remains of
1958 //course, could create a (true) replacement OUString if it matters.
1959 pStr->length = sal::static_int_cast<sal_Int32>(nWasRead);
1960 pStr->buffer[pStr->length] = 0;
1962 if (rStrm.IsEndianSwap())
1964 for (sal_Int32 i = 0; i < pStr->length; ++i)
1965 pStr->buffer[i] = OSL_SWAPWORD(pStr->buffer[i]);
1970 //take ownership of buffer and return, otherwise return empty string
1971 return pStr ? OUString(pStr, SAL_NO_ACQUIRE) : OUString();
1974 namespace
1976 template <typename T, typename O> T tmpl_convertLineEnd(const T &rIn, LineEnd eLineEnd)
1978 // Determine linebreaks and compute length
1979 bool bConvert = false; // Needs conversion
1980 sal_Int32 nStrLen = rIn.getLength();
1981 sal_Int32 nLineEndLen = (eLineEnd == LINEEND_CRLF) ? 2 : 1;
1982 sal_Int32 nLen = 0; // Target length
1983 sal_Int32 i = 0; // Source counter
1985 while (i < nStrLen)
1987 // \r or \n causes linebreak
1988 if ( (rIn[i] == '\r') || (rIn[i] == '\n') )
1990 nLen = nLen + nLineEndLen;
1992 // If set already, skip expensive test
1993 if ( !bConvert )
1995 // Do we need to convert?
1996 if ( ((eLineEnd != LINEEND_LF) && (rIn[i] == '\n')) ||
1997 ((eLineEnd == LINEEND_CRLF) && (i+1) < nStrLen && (rIn[i+1] != '\n')) ||
1998 ((eLineEnd == LINEEND_LF) &&
1999 ((rIn[i] == '\r') || ((i+1) < nStrLen && rIn[i+1] == '\r'))) ||
2000 ((eLineEnd == LINEEND_CR) &&
2001 ((rIn[i] == '\n') || ((i+1) < nStrLen && rIn[i+1] == '\n'))) )
2002 bConvert = true;
2005 // skip char if \r\n or \n\r
2006 if ( (i+1) < nStrLen && ((rIn[i+1] == '\r') || (rIn[i+1] == '\n')) &&
2007 (rIn[i] != rIn[i+1]) )
2008 ++i;
2010 else
2011 ++nLen;
2012 ++i;
2015 if (!bConvert)
2016 return rIn;
2018 // convert linebreaks, insert string
2019 O aNewData(nLen);
2020 i = 0;
2021 while (i < nStrLen)
2023 // \r or \n causes linebreak
2024 if ( (rIn[i] == '\r') || (rIn[i] == '\n') )
2026 if ( eLineEnd == LINEEND_CRLF )
2028 aNewData.append('\r');
2029 aNewData.append('\n');
2031 else
2033 if ( eLineEnd == LINEEND_CR )
2034 aNewData.append('\r');
2035 else
2036 aNewData.append('\n');
2039 if ( (i+1) < nStrLen && ((rIn[i+1] == '\r') || (rIn[i+1] == '\n')) &&
2040 (rIn[i] != rIn[i+1]) )
2041 ++i;
2043 else
2045 aNewData.append(rIn[i]);
2048 ++i;
2051 return aNewData.makeStringAndClear();
2055 OString convertLineEnd(const OString &rIn, LineEnd eLineEnd)
2057 return tmpl_convertLineEnd<OString, OStringBuffer>(rIn, eLineEnd);
2060 OUString convertLineEnd(const OUString &rIn, LineEnd eLineEnd)
2062 return tmpl_convertLineEnd<OUString, OUStringBuffer>(rIn, eLineEnd);
2065 std::size_t write_uInt32_lenPrefixed_uInt16s_FromOUString(SvStream& rStrm,
2066 const OUString &rStr)
2068 std::size_t nWritten = 0;
2069 sal_uInt32 nUnits = std::min<std::size_t>(rStr.getLength(), std::numeric_limits<sal_uInt32>::max());
2070 SAL_WARN_IF(static_cast<std::size_t>(nUnits) != static_cast<std::size_t>(rStr.getLength()),
2071 "tools.stream",
2072 "string too long for prefix count to fit in output type");
2073 rStrm.WriteUInt32(nUnits);
2074 if (rStrm.good())
2076 nWritten += sizeof(sal_uInt32);
2077 nWritten += write_uInt16s_FromOUString(rStrm, rStr, nUnits);
2079 return nWritten;
2082 std::size_t write_uInt16_lenPrefixed_uInt16s_FromOUString(SvStream& rStrm,
2083 const OUString &rStr)
2085 std::size_t nWritten = 0;
2086 sal_uInt16 nUnits = std::min<std::size_t>(rStr.getLength(), std::numeric_limits<sal_uInt16>::max());
2087 SAL_WARN_IF(nUnits != rStr.getLength(),
2088 "tools.stream",
2089 "string too long for prefix count to fit in output type");
2090 rStrm.WriteUInt16(nUnits);
2091 if (rStrm.good())
2093 nWritten += sizeof(nUnits);
2094 nWritten += write_uInt16s_FromOUString(rStrm, rStr, nUnits);
2096 return nWritten;
2099 std::size_t write_uInt16_lenPrefixed_uInt8s_FromOString(SvStream& rStrm,
2100 const OString &rStr)
2102 std::size_t nWritten = 0;
2103 sal_uInt16 nUnits = std::min<std::size_t>(rStr.getLength(), std::numeric_limits<sal_uInt16>::max());
2104 SAL_WARN_IF(static_cast<std::size_t>(nUnits) != static_cast<std::size_t>(rStr.getLength()),
2105 "tools.stream",
2106 "string too long for sal_uInt16 count to fit in output type");
2107 rStrm.WriteUInt16( nUnits );
2108 if (rStrm.good())
2110 nWritten += sizeof(sal_uInt16);
2111 nWritten += write_uInt8s_FromOString(rStrm, rStr, nUnits);
2113 return nWritten;
2116 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */