1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 #ifndef INCLUDED_TOOLS_STREAM_HXX
20 #define INCLUDED_TOOLS_STREAM_HXX
21 
22 #include <tools/toolsdllapi.h>
23 #include <tools/lineend.hxx>
24 #include <tools/ref.hxx>
25 #include <vcl/errcode.hxx>
26 #include <rtl/string.hxx>
27 #include <o3tl/typed_flags_set.hxx>
28 #include <memory>
29 
30 class StreamData;
31 
GetStoreCharSet(rtl_TextEncoding eEncoding)32 inline rtl_TextEncoding GetStoreCharSet( rtl_TextEncoding eEncoding )
33 {
34     if ( eEncoding == RTL_TEXTENCODING_ISO_8859_1 )
35         return RTL_TEXTENCODING_MS_1252;
36     else
37         return eEncoding;
38 }
39 
40 // StreamTypes
41 
42 // read, write, create,... options
43 enum class StreamMode {
44     NONE                     = 0x0000,
45     READ                     = 0x0001,  ///< allow read accesses
46     WRITE                    = 0x0002,  ///< allow write accesses
47 // file i/o
48     NOCREATE                 = 0x0004,  ///< 1 == Don't create file
49     TRUNC                    = 0x0008,  ///< Truncate _existing_ file to zero length
50     COPY_ON_SYMLINK          = 0x0010,  ///< copy-on-write for symlinks (Unix)
51 // sharing options
52     SHARE_DENYNONE           = 0x0100,
53     SHARE_DENYREAD           = 0x0200,  // overrides denynone
54     SHARE_DENYWRITE          = 0x0400,  // overrides denynone
55     SHARE_DENYALL            = 0x0800,  // overrides denyread,write,none
56 // masks
57     READWRITE                = READ | WRITE,
58     STD_READ                 = READ | SHARE_DENYNONE | NOCREATE,
59     STD_WRITE                = WRITE | SHARE_DENYALL,
60     STD_READWRITE            = READWRITE | SHARE_DENYALL
61 };
62 namespace o3tl
63 {
64     template<> struct typed_flags<StreamMode> : is_typed_flags<StreamMode, 0x0f1f> {};
65 }
66 
67 #define STREAM_SEEK_TO_BEGIN            0L
68 #define STREAM_SEEK_TO_END              SAL_MAX_UINT64
69 
70 enum class SvStreamEndian { BIG, LITTLE };
71 
72 enum class SvStreamCompressFlags {
73     NONE     = 0x0000,
74     ZBITMAP  = 0x0001,
75     NATIVE   = 0x0010,
76 };
77 namespace o3tl
78 {
79     template<> struct typed_flags<SvStreamCompressFlags> : is_typed_flags<SvStreamCompressFlags, 0x0011> {};
80 }
81 
82 class SvStream;
83 
84 typedef SvStream& (*SvStrPtr)( SvStream& );
85 
86 inline SvStream& operator<<( SvStream& rStr, SvStrPtr f );
87 
88 // SvLockBytes
89 
90 struct SvLockBytesStat
91 {
92     std::size_t nSize;
93 
SvLockBytesStatSvLockBytesStat94     SvLockBytesStat() : nSize(0) {}
95 };
96 
97 class TOOLS_DLLPUBLIC SvLockBytes: public virtual SvRefBase
98 {
99     SvStream * m_pStream;
100     bool const m_bOwner;
101     bool m_bSync;
102 
103 protected:
104     void close();
105 
106 public:
107 
SvLockBytes()108     SvLockBytes() : m_pStream(nullptr), m_bOwner(false), m_bSync(false) {}
109 
SvLockBytes(SvStream * pTheStream,bool bTheOwner=false)110     SvLockBytes(SvStream * pTheStream, bool bTheOwner = false) :
111         m_pStream(pTheStream), m_bOwner(bTheOwner), m_bSync(false) {}
112 
~SvLockBytes()113     virtual ~SvLockBytes() override { close(); }
114 
GetStream() const115     const SvStream * GetStream() const { return m_pStream; }
116 
SetSynchronMode(bool bTheSync=true)117     void            SetSynchronMode(bool bTheSync = true) { m_bSync = bTheSync; }
IsSynchronMode() const118     bool            IsSynchronMode() const { return m_bSync; }
119 
120     virtual ErrCode ReadAt(sal_uInt64 nPos, void * pBuffer, std::size_t nCount,
121                            std::size_t * pRead) const;
122     virtual ErrCode WriteAt(sal_uInt64 nPos, const void * pBuffer, std::size_t nCount,
123                             std::size_t * pWritten);
124 
125     virtual ErrCode Flush() const;
126 
127     virtual ErrCode SetSize(sal_uInt64 nSize);
128 
129     virtual ErrCode Stat(SvLockBytesStat * pStat) const;
130 };
131 
132 typedef tools::SvRef<SvLockBytes> SvLockBytesRef;
133 
134 // SvStream
135 
136 class TOOLS_DLLPUBLIC SvStream
137 {
138 private:
139     // LockBytes Interface
140     SvLockBytesRef  m_xLockBytes; ///< Default implementation
141     sal_uInt64      m_nActPos;
142 
143     // buffer management
144     std::unique_ptr<sal_uInt8[]>
145                     m_pRWBuf;     ///< Points to read/write buffer
146     sal_uInt8*      m_pBufPos;    ///< m_pRWBuf + m_nBufActualPos
147     sal_uInt16      m_nBufSize;   ///< Allocated size of buffer
148     sal_uInt16      m_nBufActualLen; ///< Length of used segment of buffer
149                                   ///< = m_nBufSize, if EOF did not occur
150     sal_uInt16      m_nBufActualPos; ///< current position in buffer (0..m_nBufSize-1)
151     sal_uInt16      m_nBufFree;   ///< number of free slots in buffer to IO of type eIOMode
152     bool            m_isIoRead;
153     bool            m_isIoWrite;
154 
155     // Error codes, conversion, compression, ...
156     bool            m_isDirty;  ///< true: Stream != buffer content
157     bool            m_isSwap;
158     bool            m_isEof;
159     ErrCode         m_nError;
160     SvStreamEndian  m_nEndian;
161     SvStreamCompressFlags m_nCompressMode;
162     LineEnd         m_eLineDelimiter;
163     rtl_TextEncoding m_eStreamCharSet;
164 
165     // Encryption
166     OString m_aCryptMaskKey;// aCryptMaskKey.getLength != 0  -> Encryption used
167     unsigned char   m_nCryptMask;
168 
169     // Userdata
170     sal_Int32       m_nVersion;   // for external use
171 
172                     SvStream ( const SvStream& rStream ) = delete;
173     SvStream&       operator=( const SvStream& rStream ) = delete;
174 
175 protected:
176     sal_uInt64      m_nBufFilePos; ///< File position of pBuf[0]
177     StreamMode      m_eStreamMode;
178     bool            m_isWritable;
179 
180     virtual std::size_t GetData( void* pData, std::size_t nSize );
181     virtual std::size_t PutData( const void* pData, std::size_t nSize );
182     virtual sal_uInt64 SeekPos( sal_uInt64 nPos );
183     virtual void    FlushData();
184     virtual void    SetSize(sal_uInt64 nSize);
185 
186     void            FlushBuffer();
187     void            ClearError();
188     void            ClearBuffer();
189 
190     // encrypt and write in blocks
191     std::size_t     CryptAndWriteBuffer( const void* pStart, std::size_t nLen );
192     void            EncryptBuffer( void* pStart, std::size_t nLen ) const;
193 
194 public:
195                     SvStream();
196                     SvStream( SvLockBytes *pLockBytes);
197     virtual         ~SvStream();
198 
GetLockBytes() const199     SvLockBytes*    GetLockBytes() const { return m_xLockBytes.get(); }
200 
GetError() const201     ErrCode         GetError() const { return m_nError.IgnoreWarning(); }
GetErrorCode() const202     ErrCode const & GetErrorCode() const { return m_nError; }
203     void            SetError( ErrCode nErrorCode );
204     virtual void    ResetError();
205 
206     void            SetEndian( SvStreamEndian SvStreamEndian );
GetEndian() const207     SvStreamEndian  GetEndian() const { return m_nEndian; }
208     /// returns status of endian swap flag
IsEndianSwap() const209     bool            IsEndianSwap() const { return m_isSwap; }
210 
SetCompressMode(SvStreamCompressFlags nNewMode)211     void            SetCompressMode( SvStreamCompressFlags nNewMode )
212                         { m_nCompressMode = nNewMode; }
GetCompressMode() const213     SvStreamCompressFlags GetCompressMode() const { return m_nCompressMode; }
214 
215     void SetCryptMaskKey(const OString& rCryptMaskKey);
216 
SetStreamCharSet(rtl_TextEncoding eCharSet)217     void            SetStreamCharSet( rtl_TextEncoding eCharSet )
218                         { m_eStreamCharSet = eCharSet; }
GetStreamCharSet() const219     rtl_TextEncoding GetStreamCharSet() const { return m_eStreamCharSet; }
220 
SetLineDelimiter(LineEnd eLineEnd)221     void            SetLineDelimiter( LineEnd eLineEnd )
222                         { m_eLineDelimiter = eLineEnd; }
GetLineDelimiter() const223     LineEnd         GetLineDelimiter() const { return m_eLineDelimiter; }
224 
225     SvStream&       ReadUInt16( sal_uInt16& rUInt16 );
226     SvStream&       ReadUInt32( sal_uInt32& rUInt32 );
227     SvStream&       ReadUInt64( sal_uInt64& rUInt64 );
228     SvStream&       ReadInt16( sal_Int16& rInt16 );
229     SvStream&       ReadInt32( sal_Int32& rInt32 );
230     SvStream&       ReadInt64(sal_Int64 & rInt64);
231     SvStream&       ReadSChar( signed char& rChar );
232     SvStream&       ReadChar( char& rChar );
233     SvStream&       ReadUChar( unsigned char& rChar );
234     SvStream&       ReadUtf16( sal_Unicode& rUtf16 );
235     SvStream&       ReadCharAsBool( bool& rBool );
236     SvStream&       ReadFloat( float& rFloat );
237     SvStream&       ReadDouble( double& rDouble );
238     SvStream&       ReadStream( SvStream& rStream );
239 
240     SvStream&       WriteUInt16( sal_uInt16 nUInt16 );
241     SvStream&       WriteUInt32( sal_uInt32 nUInt32 );
242     SvStream&       WriteUInt64( sal_uInt64 nuInt64 );
243     SvStream&       WriteInt16( sal_Int16 nInt16 );
244     SvStream&       WriteInt32( sal_Int32 nInt32 );
245     SvStream&       WriteInt64( sal_Int64 nInt64 );
246     SvStream&       WriteUInt8( sal_uInt8 nuInt8 );
247     SvStream&       WriteUnicode( sal_Unicode );
WriteOString(const OString & rStr)248     SvStream&       WriteOString(const OString& rStr)
249                         { WriteBytes(rStr.getStr(), rStr.getLength()); return *this; }
250     SvStream&       WriteStream( SvStream& rStream );
251     sal_uInt64      WriteStream( SvStream& rStream, sal_uInt64 nSize );
252 
WriteBool(bool b)253     SvStream&       WriteBool( bool b )
254                         { return WriteUChar(static_cast<unsigned char>(b)); }
255     SvStream&       WriteSChar( signed char nChar );
256     SvStream&       WriteChar( char nChar );
257     SvStream&       WriteUChar( unsigned char nChar );
258     SvStream&       WriteFloat( float nFloat );
259     SvStream&       WriteDouble( const double& rDouble );
260     SvStream&       WriteCharPtr( const char* pBuf );
261 
262     SvStream&       WriteUInt32AsString( sal_uInt32 nUInt32 );
263     SvStream&       WriteInt32AsString( sal_Int32 nInt32 );
264 
265     std::size_t     ReadBytes( void* pData, std::size_t nSize );
266     std::size_t     WriteBytes( const void* pData, std::size_t nSize );
267     sal_uInt64      Seek( sal_uInt64 nPos );
268     sal_uInt64      SeekRel( sal_Int64 nPos );
Tell() const269     sal_uInt64      Tell() const { return m_nBufFilePos + m_nBufActualPos;  }
270     virtual sal_uInt64 TellEnd();
271     // length between current (Tell()) pos and end of stream
272     sal_uInt64      remainingSize();
273     void            Flush();
274     // next Tell() <= nSize
275     bool            SetStreamSize( sal_uInt64 nSize );
276 
277     /** Read a line of bytes.
278 
279         @param nMaxBytesToRead
280                    Maximum of bytes to read, if line is longer it will be
281                    truncated.
282 
283         @note NOTE that the default is one character less than STRING_MAXLEN to
284               prevent problems after conversion to String that may be lurking
285               in various places doing something like
286               @code
287                 for (sal_uInt16 i=0; i < aString.Len(); ++i)
288               @endcode
289               causing endless loops ...
290     */
291     bool            ReadLine( OString& rStr, sal_Int32 nMaxBytesToRead = 0xFFFE );
292     bool            WriteLine( const OString& rStr );
293 
294     /** Read a line of bytes.
295 
296         @param nMaxBytesToRead
297                    Maximum of bytes to read, if line is longer it will be
298                    truncated.
299 
300         @note NOTE that the default is one character less than STRING_MAXLEN to
301               prevent problems after conversion to String that may be lurking
302               in various places doing something like
303               @code
304                 for (sal_uInt16 i=0; i < aString.Len(); ++i)
305               @endcode
306               causing endless loops ...
307     */
308     bool            ReadByteStringLine( OUString& rStr, rtl_TextEncoding eSrcCharSet,
309                                         sal_Int32 nMaxBytesToRead = 0xFFFE );
310     bool            WriteByteStringLine( const OUString& rStr, rtl_TextEncoding eDestCharSet );
311 
312     /// Switch to no endian swapping and write 0xfeff
313     void            StartWritingUnicodeText();
314 
315     /** If eReadBomCharSet==RTL_TEXTENCODING_DONTKNOW: read 16bit, if 0xfeff do
316         nothing (UTF-16), if 0xfffe switch endian swapping (UTF-16), if 0xefbb
317         or 0xbbef read another byte and check for UTF-8. If no UTF-* BOM was
318         detected put all read bytes back. This means that if 2 bytes were read
319         it was an UTF-16 BOM, if 3 bytes were read it was an UTF-8 BOM. There
320         is no UTF-7, UTF-32 or UTF-EBCDIC BOM detection!
321 
322         If eReadBomCharSet!=RTL_TEXTENCODING_DONTKNOW: only read a BOM of that
323         encoding and switch endian swapping if UTF-16 and 0xfffe. */
324     void            StartReadingUnicodeText( rtl_TextEncoding eReadBomCharSet );
325 
326     /** Read a line of Unicode.
327 
328         @param nMaxCodepointsToRead
329                    Maximum of codepoints (UCS-2 or UTF-16 pairs, not bytes) to
330                    read, if line is longer it will be truncated.
331     */
332     bool            ReadUniStringLine(OUString& rStr, sal_Int32 nMaxCodepointsToRead);
333     /** Read a 32bit length prefixed sequence of utf-16 if
334         eSrcCharSet==RTL_TEXTENCODING_UNICODE, otherwise read a 16bit length
335         prefixed sequence of bytes and convert from eSrcCharSet */
336     OUString        ReadUniOrByteString(rtl_TextEncoding eSrcCharSet);
337     /** Write a 32bit length prefixed sequence of utf-16 if
338         eSrcCharSet==RTL_TEXTENCODING_UNICODE, otherwise convert to eSrcCharSet
339         and write a 16bit length prefixed sequence of bytes */
340     SvStream&       WriteUniOrByteString( const OUString& rStr, rtl_TextEncoding eDestCharSet );
341 
342     /** Read a line of Unicode if eSrcCharSet==RTL_TEXTENCODING_UNICODE,
343         otherwise read a line of Bytecode and convert from eSrcCharSet
344 
345         @param nMaxCodepointsToRead
346                    Maximum of codepoints (2 bytes if Unicode, bytes if not
347                    Unicode) to read, if line is longer it will be truncated.
348 
349         @note NOTE that the default is one character less than STRING_MAXLEN to
350               prevent problems after conversion to String that may be lurking in
351               various places doing something like
352               @code
353                 for (sal_uInt16 i=0; i < aString.Len(); ++i)
354               @endcode
355               causing endless loops ...
356     */
357     bool            ReadUniOrByteStringLine( OUString& rStr, rtl_TextEncoding eSrcCharSet,
358                                              sal_Int32 nMaxCodepointsToRead = 0xFFFE );
359     /** Write a sequence of Unicode characters if
360         eDestCharSet==RTL_TEXTENCODING_UNICODE, otherwise write a sequence of
361         Bytecodes converted to eDestCharSet */
362     bool            WriteUnicodeOrByteText( const OUString& rStr, rtl_TextEncoding eDestCharSet );
WriteUnicodeOrByteText(const OUString & rStr)363     bool            WriteUnicodeOrByteText( const OUString& rStr )
364                     { return WriteUnicodeOrByteText( rStr, GetStreamCharSet() ); }
365 
366     /** Write a Unicode character if eDestCharSet==RTL_TEXTENCODING_UNICODE,
367         otherwise write as Bytecode converted to eDestCharSet.
368 
369         This may result in more than one byte being written if a multi byte
370         encoding (e.g. UTF7, UTF8) is chosen. */
371     bool            WriteUniOrByteChar( sal_Unicode ch, rtl_TextEncoding eDestCharSet );
WriteUniOrByteChar(sal_Unicode ch)372     bool            WriteUniOrByteChar( sal_Unicode ch )
373                     { return WriteUniOrByteChar( ch, GetStreamCharSet() ); }
374 
375     void            SetBufferSize( sal_uInt16 m_nBufSize );
GetBufferSize() const376     sal_uInt16      GetBufferSize() const { return m_nBufSize; }
377 
378     void            RefreshBuffer();
379 
IsWritable() const380     bool            IsWritable() const { return m_isWritable; }
GetStreamMode() const381     StreamMode      GetStreamMode() const { return m_eStreamMode; }
382 
GetVersion() const383     sal_Int32       GetVersion() const { return m_nVersion; }
SetVersion(sal_Int32 n)384     void            SetVersion( sal_Int32 n ) { m_nVersion = n; }
385 
386     friend SvStream& operator<<( SvStream& rStr, SvStrPtr f ); // for Manips
387 
388     /// end of input seen during previous i/o operation
eof() const389     bool eof() const { return m_isEof; }
390 
391     /// stream is broken
bad() const392     bool bad() const { return GetError() != ERRCODE_NONE; }
393 
394     /** Get state
395 
396         If the state is good() the previous i/o operation succeeded.
397 
398         If the state is good(), the next input operation might succeed;
399         otherwise, it will fail.
400 
401         Applying an input operation to a stream that is not in the good() state
402         is a null operation as far as the variable being read into is concerned.
403 
404         If we try to read into a variable v and the operation fails, the value
405         of v should be unchanged,
406     */
good() const407     bool good() const { return !(eof() || bad()); }
408 
409 private:
410     template<typename T>
readNumberWithoutSwap(T & rDataDest)411     void readNumberWithoutSwap(T& rDataDest)
412     { readNumberWithoutSwap_(&rDataDest, sizeof(rDataDest)); }
413 
414     void readNumberWithoutSwap_(void * pDataDest, int nDataSize);
415 
416     template<typename T>
writeNumberWithoutSwap(T const & rDataSrc)417     void writeNumberWithoutSwap(T const & rDataSrc)
418     { writeNumberWithoutSwap_(&rDataSrc, sizeof(rDataSrc)); }
419 
420     void writeNumberWithoutSwap_(const void * pDataSrc, int nDataSize);
421 };
422 
operator <<(SvStream & rStr,SvStrPtr f)423 inline SvStream& operator<<( SvStream& rStr, SvStrPtr f )
424 {
425     (*f)(rStr);
426     return rStr;
427 }
428 
429 TOOLS_DLLPUBLIC SvStream& endl( SvStream& rStr );
430 /// same as endl() but Unicode
431 TOOLS_DLLPUBLIC SvStream& endlu( SvStream& rStr );
432 /// call endlu() if m_eStreamCharSet==RTL_TEXTECODING_UNICODE otherwise endl()
433 TOOLS_DLLPUBLIC SvStream& endlub( SvStream& rStr );
434 
435 /// Attempt to read nUnits 8bit units to an OString, returned OString's
436 /// length is number of units successfully read
437 TOOLS_DLLPUBLIC OString read_uInt8s_ToOString(SvStream& rStrm,
438     std::size_t nUnits);
439 
440 /// Attempt to read nUnits 8bit units to an OUString
read_uInt8s_ToOUString(SvStream & rStrm,std::size_t nUnits,rtl_TextEncoding eEnc)441 inline OUString read_uInt8s_ToOUString(SvStream& rStrm,
442     std::size_t nUnits, rtl_TextEncoding eEnc)
443 {
444     return OStringToOUString(read_uInt8s_ToOString(rStrm, nUnits), eEnc);
445 }
446 
447 /// Attempt to read nUnits 16bit units to an OUString, returned
448 /// OUString's length is number of units successfully read
449 TOOLS_DLLPUBLIC OUString read_uInt16s_ToOUString(SvStream& rStrm,
450     std::size_t nUnits);
451 
452 /// Attempt to read a pascal-style length (of type prefix) prefixed sequence of
453 /// 16bit units to an OUString, returned OString's length is number of
454 /// units successfully read.
read_uInt16_lenPrefixed_uInt16s_ToOUString(SvStream & rStrm)455 inline OUString read_uInt16_lenPrefixed_uInt16s_ToOUString(SvStream& rStrm)
456 {
457     sal_uInt16 nUnits = 0;
458     rStrm.ReadUInt16( nUnits );
459     return read_uInt16s_ToOUString(rStrm, nUnits);
460 }
461 
read_uInt32_lenPrefixed_uInt16s_ToOUString(SvStream & rStrm)462 inline OUString read_uInt32_lenPrefixed_uInt16s_ToOUString(SvStream& rStrm)
463 {
464     sal_uInt32 nUnits = 0;
465     rStrm.ReadUInt32( nUnits );
466     return read_uInt16s_ToOUString(rStrm, nUnits);
467 }
468 
469 /// Attempt to write a prefixed sequence of nUnits 16bit units from an OUString,
470 /// returned value is number of bytes written
471 TOOLS_DLLPUBLIC std::size_t write_uInt16s_FromOUString(SvStream& rStrm,
472     const OUString& rStr, std::size_t nUnits);
473 
write_uInt16s_FromOUString(SvStream & rStrm,const OUString & rStr)474 inline std::size_t write_uInt16s_FromOUString(SvStream& rStrm,
475     const OUString& rStr)
476 {
477     return write_uInt16s_FromOUString(rStrm, rStr, rStr.getLength());
478 }
479 
480 /// Attempt to write a pascal-style length (of type prefix) prefixed sequence
481 /// of 16bit units from an OUString, returned value is number of bytes written
482 /// (including byte-count of prefix)
483 std::size_t write_uInt32_lenPrefixed_uInt16s_FromOUString(SvStream& rStrm,
484                                                 const OUString &rStr);
485 
486 /// Attempt to write a pascal-style length (of type prefix) prefixed sequence
487 /// of 16bit units from an OUString, returned value is number of bytes written
488 /// (including byte-count of prefix)
489 TOOLS_DLLPUBLIC std::size_t write_uInt16_lenPrefixed_uInt16s_FromOUString(SvStream& rStrm,
490                                                 const OUString &rStr);
491 
492 /// Attempt to read 8bit units to an OString until a zero terminator is
493 /// encountered, returned OString's length is number of units *definitely*
494 /// successfully read, check SvStream::good() to see if null terminator was
495 /// successfully read
496 TOOLS_DLLPUBLIC OString read_zeroTerminated_uInt8s_ToOString(SvStream& rStrm);
497 
498 /// Attempt to read 8bit units assuming source encoding eEnc to an OUString
499 /// until a zero terminator is encountered. Check SvStream::good() to see if
500 /// null terminator was successfully read
501 TOOLS_DLLPUBLIC OUString read_zeroTerminated_uInt8s_ToOUString(SvStream& rStrm, rtl_TextEncoding eEnc);
502 
503 /// Attempt to read a pascal-style length (of type prefix) prefixed sequence of
504 /// 8bit units to an OString, returned OString's length is number of units
505 /// successfully read.
read_uInt32_lenPrefixed_uInt8s_ToOString(SvStream & rStrm)506 inline OString read_uInt32_lenPrefixed_uInt8s_ToOString(SvStream& rStrm)
507 {
508     sal_uInt32 nUnits = 0;
509     rStrm.ReadUInt32(nUnits);
510     return read_uInt8s_ToOString(rStrm, nUnits);
511 }
read_uInt16_lenPrefixed_uInt8s_ToOString(SvStream & rStrm)512 inline OString read_uInt16_lenPrefixed_uInt8s_ToOString(SvStream& rStrm)
513 {
514     sal_uInt16 nUnits = 0;
515     rStrm.ReadUInt16(nUnits);
516     return read_uInt8s_ToOString(rStrm, nUnits);
517 }
518 
read_uInt8_lenPrefixed_uInt8s_ToOString(SvStream & rStrm)519 inline OString read_uInt8_lenPrefixed_uInt8s_ToOString(SvStream& rStrm)
520 {
521     sal_uInt8 nUnits = 0;
522     rStrm.ReadUChar(nUnits);
523     return read_uInt8s_ToOString(rStrm, nUnits);
524 }
525 
read_uInt16_lenPrefixed_uInt8s_ToOUString(SvStream & rStrm,rtl_TextEncoding eEnc)526 inline OUString read_uInt16_lenPrefixed_uInt8s_ToOUString(SvStream& rStrm,
527                                                           rtl_TextEncoding eEnc)
528 {
529     return OStringToOUString(read_uInt16_lenPrefixed_uInt8s_ToOString(rStrm), eEnc);
530 }
531 
read_uInt8_lenPrefixed_uInt8s_ToOUString(SvStream & rStrm,rtl_TextEncoding eEnc)532 inline OUString read_uInt8_lenPrefixed_uInt8s_ToOUString(SvStream& rStrm,
533                                                          rtl_TextEncoding eEnc)
534 {
535     return OStringToOUString(read_uInt8_lenPrefixed_uInt8s_ToOString(rStrm), eEnc);
536 }
537 
538 /// Attempt to write a prefixed sequence of nUnits 8bit units from an OString,
539 /// returned value is number of bytes written
write_uInt8s_FromOString(SvStream & rStrm,const OString & rStr,std::size_t nUnits)540 inline std::size_t write_uInt8s_FromOString(SvStream& rStrm, const OString& rStr,
541                                                          std::size_t nUnits)
542 {
543     return rStrm.WriteBytes(rStr.getStr(), nUnits);
544 }
545 
write_uInt8s_FromOString(SvStream & rStrm,const OString & rStr)546 inline std::size_t write_uInt8s_FromOString(SvStream& rStrm, const OString& rStr)
547 {
548     return write_uInt8s_FromOString(rStrm, rStr, rStr.getLength());
549 }
550 
551 /// Attempt to write a pascal-style length (of type prefix) prefixed
552 /// sequence of units from a string-type, returned value is number of bytes
553 /// written (including byte-count of prefix)
554 TOOLS_DLLPUBLIC std::size_t write_uInt16_lenPrefixed_uInt8s_FromOString(SvStream& rStrm,
555                                               const OString &rStr);
556 
557 /// Attempt to write a pascal-style length (of type prefix) prefixed sequence
558 /// of 8bit units from an OUString, returned value is number of bytes written
559 /// (including byte-count of prefix)
write_uInt16_lenPrefixed_uInt8s_FromOUString(SvStream & rStrm,const OUString & rStr,rtl_TextEncoding eEnc)560 inline std::size_t write_uInt16_lenPrefixed_uInt8s_FromOUString(SvStream& rStrm,
561                                                const OUString &rStr,
562                                                rtl_TextEncoding eEnc)
563 {
564     return write_uInt16_lenPrefixed_uInt8s_FromOString(rStrm, OUStringToOString(rStr, eEnc));
565 }
566 
567 [[nodiscard]] TOOLS_DLLPUBLIC bool checkSeek(SvStream &rSt, sal_uInt64 nOffset);
568 
569 // FileStream
570 
571 class TOOLS_DLLPUBLIC SvFileStream final : public SvStream
572 {
573 private:
574     std::unique_ptr<StreamData>
575                     pInstanceData;
576     OUString        aFilename;
577 #if defined(_WIN32)
578     sal_uInt16      nLockCounter;
579 #endif
580     bool            bIsOpen;
581 
582     SvFileStream (const SvFileStream&) = delete;
583     SvFileStream & operator= (const SvFileStream&) = delete;
584 
585     bool LockRange( sal_uInt64 nByteOffset, std::size_t nBytes );
586     bool UnlockRange( sal_uInt64 nByteOffset, std::size_t nBytes );
587     bool LockFile();
588     void UnlockFile();
589 
590     virtual std::size_t GetData( void* pData, std::size_t nSize ) override;
591     virtual std::size_t PutData( const void* pData, std::size_t nSize ) override;
592     virtual sal_uInt64 SeekPos( sal_uInt64 nPos ) override;
593     virtual void    SetSize( sal_uInt64 nSize ) override;
594     virtual void    FlushData() override;
595 
596 public:
597                     // Switches to Read StreamMode on failed attempt of Write opening
598                     SvFileStream( const OUString& rFileName, StreamMode eOpenMode );
599                     SvFileStream();
600                     virtual ~SvFileStream() override;
601 
602     virtual void    ResetError() override;
603 
604     void            Open( const OUString& rFileName, StreamMode eOpenMode );
605     void            Close();
IsOpen() const606     bool            IsOpen() const { return bIsOpen; }
607 
GetFileName() const608     const OUString& GetFileName() const { return aFilename; }
609 };
610 
611 // MemoryStream
612 
613 class TOOLS_DLLPUBLIC SvMemoryStream : public SvStream
614 {
615     SvMemoryStream (const SvMemoryStream&) = delete;
616     SvMemoryStream & operator= (const SvMemoryStream&) = delete;
617 
618 protected:
619     std::size_t     nSize;
620     std::size_t     nResize;
621     std::size_t     nPos;
622     std::size_t     nEndOfData;
623     sal_uInt8*      pBuf;
624     bool            bOwnsData;
625 
626     virtual std::size_t GetData( void* pData, std::size_t nSize ) override;
627     virtual std::size_t PutData( const void* pData, std::size_t nSize ) override;
628     virtual sal_uInt64 SeekPos( sal_uInt64 nPos ) override;
629     virtual void    SetSize( sal_uInt64 nSize ) override;
630     virtual void    FlushData() override;
631 
632     /// AllocateMemory must update pBuf accordingly
633     /// - pBuf: Address of new block
634     void    AllocateMemory( std::size_t nSize );
635 
636     /// ReAllocateMemory must update the following variables:
637     /// - pBuf: Address of new block
638     /// - nEndOfData: Set to nNewSize-1 , if outside of block
639     ///               Set to 0 , if new block size is 0 bytes
640     /// - nSize: New block size
641     /// - nPos: Set to 0 if position outside of block
642     bool    ReAllocateMemory( long nDiff );
643 
644     /// Is called when this stream allocated the buffer or the buffer is
645     /// resized. FreeMemory may need to NULLify handles in derived classes.
646     void    FreeMemory();
647 
648 public:
649                     SvMemoryStream( void* pBuf, std::size_t nSize, StreamMode eMode);
650                     SvMemoryStream( std::size_t nInitSize=512, std::size_t nResize=64 );
651                     virtual ~SvMemoryStream() override;
652 
653     virtual void    ResetError() override;
654 
655     sal_uInt64      GetSize();
GetEndOfData() const656     std::size_t     GetEndOfData() const { return nEndOfData; }
GetData()657     const void*     GetData() { Flush(); return pBuf; }
658 
659     // return the buffer currently in use, and allocate a new buffer internally
660     void*           SwitchBuffer();
661     // the buffer is not owned by this class
662     void            SetBuffer( void* pBuf, std::size_t nSize, std::size_t nEOF );
663 
ObjectOwnsMemory(bool bOwn)664     void            ObjectOwnsMemory( bool bOwn ) { bOwnsData = bOwn; }
SetResizeOffset(std::size_t nNewResize)665     void            SetResizeOffset( std::size_t nNewResize ) { nResize = nNewResize; }
TellEnd()666     virtual sal_uInt64 TellEnd() override { FlushBuffer(); return nEndOfData; }
667 };
668 
669 #endif
670 
671 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
672