Coverage Report

Created: 2026-10-14 09:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/tools/source/stream/stream.cxx
Line
Count
Source
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
20
// TODO: Read->RefreshBuffer-> React to changes from m_nBufActualLen
21
22
#include <sal/config.h>
23
24
#include <array>
25
#include <cassert>
26
#include <cstddef>
27
#include <memory>
28
29
#include <string.h>
30
#include <string_view>
31
32
#include <o3tl/safeint.hxx>
33
#include <o3tl/untaint.hxx>
34
#include <osl/endian.h>
35
#include <osl/diagnose.h>
36
#include <rtl/strbuf.hxx>
37
#include <rtl/string.hxx>
38
#include <rtl/ustrbuf.hxx>
39
#include <sal/log.hxx>
40
#include <tools/long.hxx>
41
42
#include <comphelper/fileformat.h>
43
#include <comphelper/fileurl.hxx>
44
#include <comphelper/scopeguard.hxx>
45
46
#include <boost/version.hpp>
47
#if BOOST_VERSION >= 108600
48
#include <boost/core/pointer_in_range.hpp>
49
#endif
50
51
#include <unicode/ucsdet.h>
52
53
#include <frozen/bits/elsa_std.h>
54
#include <frozen/unordered_map.h>
55
56
static void swapNibbles(unsigned char &c)
57
0
{
58
0
    unsigned char nSwapTmp=c;
59
0
    nSwapTmp <<= 4;
60
0
    c >>= 4;
61
0
    c |= nSwapTmp;
62
0
}
63
64
#include <tools/debug.hxx>
65
#include <tools/stream.hxx>
66
#include <osl/thread.h>
67
#include <algorithm>
68
69
// !!! Do not inline if already the operators <<,>> are inline
70
template <typename T, std::enable_if_t<std::is_integral_v<T> && sizeof(T) == 2, int> = 0>
71
static void SwapNumber(T& r)
72
896k
    {   r = OSL_SWAPWORD(r);   }
stream.cxx:_ZL10SwapNumberIDsTnNSt3__19enable_ifIXaasr3stdE13is_integral_vIT_EeqstS2_Li2EEiE4typeELi0EEvRS2_
Line
Count
Source
72
773k
    {   r = OSL_SWAPWORD(r);   }
stream.cxx:_ZL10SwapNumberItTnNSt3__19enable_ifIXaasr3stdE13is_integral_vIT_EeqstS2_Li2EEiE4typeELi0EEvRS2_
Line
Count
Source
72
48.6k
    {   r = OSL_SWAPWORD(r);   }
stream.cxx:_ZL10SwapNumberIsTnNSt3__19enable_ifIXaasr3stdE13is_integral_vIT_EeqstS2_Li2EEiE4typeELi0EEvRS2_
Line
Count
Source
72
73.5k
    {   r = OSL_SWAPWORD(r);   }
73
template <typename T, std::enable_if_t<std::is_integral_v<T> && sizeof(T) == 4, int> = 0>
74
static void SwapNumber(T& r)
75
12.2M
    {   r = OSL_SWAPDWORD(r);   }
stream.cxx:_ZL10SwapNumberIjTnNSt3__19enable_ifIXaasr3stdE13is_integral_vIT_EeqstS2_Li4EEiE4typeELi0EEvRS2_
Line
Count
Source
75
12.2M
    {   r = OSL_SWAPDWORD(r);   }
stream.cxx:_ZL10SwapNumberIiTnNSt3__19enable_ifIXaasr3stdE13is_integral_vIT_EeqstS2_Li4EEiE4typeELi0EEvRS2_
Line
Count
Source
75
6.29k
    {   r = OSL_SWAPDWORD(r);   }
76
template <typename T, std::enable_if_t<std::is_integral_v<T> && sizeof(T) == 8, int> = 0>
77
static void SwapNumber(T& r)
78
18.1k
    {
79
18.1k
        union
80
18.1k
        {
81
18.1k
            T n;
82
18.1k
            sal_uInt32 c[2];
83
18.1k
        } s;
84
85
18.1k
        s.n = r;
86
18.1k
        std::swap(s.c[0], s.c[1]); // swap the 32 bit words
87
        // swap the bytes in the words
88
18.1k
        s.c[0] = OSL_SWAPDWORD(s.c[0]);
89
18.1k
        s.c[1] = OSL_SWAPDWORD(s.c[1]);
90
18.1k
        r = s.n;
91
18.1k
    }
stream.cxx:_ZL10SwapNumberImTnNSt3__19enable_ifIXaasr3stdE13is_integral_vIT_EeqstS2_Li8EEiE4typeELi0EEvRS2_
Line
Count
Source
78
18.1k
    {
79
18.1k
        union
80
18.1k
        {
81
18.1k
            T n;
82
18.1k
            sal_uInt32 c[2];
83
18.1k
        } s;
84
85
18.1k
        s.n = r;
86
18.1k
        std::swap(s.c[0], s.c[1]); // swap the 32 bit words
87
        // swap the bytes in the words
88
18.1k
        s.c[0] = OSL_SWAPDWORD(s.c[0]);
89
18.1k
        s.c[1] = OSL_SWAPDWORD(s.c[1]);
90
18.1k
        r = s.n;
91
18.1k
    }
Unexecuted instantiation: stream.cxx:_ZL10SwapNumberIlTnNSt3__19enable_ifIXaasr3stdE13is_integral_vIT_EeqstS2_Li8EEiE4typeELi0EEvRS2_
92
93
#ifdef UNX
94
static void SwapFloat( float& r )
95
0
    {
96
0
        union
97
0
        {
98
0
            float f;
99
0
            sal_uInt32 c;
100
0
        } s;
101
102
0
        s.f = r;
103
0
        s.c = OSL_SWAPDWORD( s.c );
104
0
        r = s.f;
105
0
    }
106
107
static void SwapDouble( double& r )
108
0
    {
109
0
        if( sizeof(double) != 8 )
110
0
        {
111
0
          SAL_WARN( "tools.stream", "Can only swap 8-Byte-doubles" );
112
0
        }
113
0
        else
114
0
        {
115
0
            union
116
0
            {
117
0
                double d;
118
0
                sal_uInt32 c[2];
119
0
            } s;
120
121
0
            s.d = r;
122
0
            s.c[0] ^= s.c[1]; // swap 32-bit values in situ
123
0
            s.c[1] ^= s.c[0];
124
0
            s.c[0] ^= s.c[1];
125
0
            s.c[0] = OSL_SWAPDWORD(s.c[0]); // swap dword itself in situ
126
0
            s.c[1] = OSL_SWAPDWORD(s.c[1]);
127
0
            r = s.d;
128
0
        }
129
0
    }
130
#endif
131
132
//SDO
133
134
void SvStream::readNumberWithoutSwap_(void * pDataDest, int nDataSize)
135
389M
{
136
389M
    if (m_isIoRead && nDataSize <= m_nBufFree)
137
98.0M
    {
138
441M
        for (int i = 0; i < nDataSize; i++)
139
343M
            static_cast<char*>(pDataDest)[i] = m_pBufPos[i];
140
98.0M
        m_nBufActualPos += nDataSize;
141
98.0M
        m_pBufPos += nDataSize;
142
98.0M
        m_nBufFree -= nDataSize;
143
98.0M
    }
144
291M
    else
145
291M
    {
146
291M
        ReadBytes( pDataDest, nDataSize );
147
291M
    }
148
389M
}
149
150
151
void SvStream::writeNumberWithoutSwap_(const void * pDataSrc, int nDataSize)
152
76.0M
{
153
76.0M
    if (m_isIoWrite && nDataSize <= m_nBufFree)
154
16.2M
    {
155
79.5M
        for (int i = 0; i < nDataSize; i++)
156
63.2M
            m_pBufPos[i] = static_cast<const char*>(pDataSrc)[i];
157
16.2M
        m_nBufFree -= nDataSize;
158
16.2M
        m_nBufActualPos += nDataSize;
159
16.2M
        if (m_nBufActualPos > m_nBufActualLen)
160
16.2M
            m_nBufActualLen = m_nBufActualPos;
161
16.2M
        m_pBufPos += nDataSize;
162
16.2M
        m_isDirty = true;
163
16.2M
    }
164
59.8M
    else
165
59.8M
    {
166
59.8M
        WriteBytes( pDataSrc, nDataSize );
167
59.8M
    }
168
76.0M
}
169
170
171
232k
SvLockBytes::~SvLockBytes() { close(); }
172
173
void SvLockBytes::close()
174
232k
{
175
232k
    (void)this;
176
232k
}
177
178
179
// virtual
180
ErrCode SvLockBytes::ReadAt(sal_uInt64 const , void * , std::size_t ,
181
                            std::size_t * ) const
182
0
{
183
0
    OSL_FAIL("SvLockBytes::ReadAt(): Bad stream");
184
0
    return ERRCODE_NONE;
185
0
}
186
187
// virtual
188
ErrCode SvLockBytes::WriteAt(sal_uInt64 const , const void * , std::size_t ,
189
                             std::size_t * )
190
0
{
191
0
    OSL_FAIL("SvLockBytes::WriteAt(): Bad stream");
192
0
    return ERRCODE_NONE;
193
0
}
194
195
// virtual
196
ErrCode SvLockBytes::Flush() const
197
0
{
198
0
    OSL_FAIL("SvLockBytes::Flush(): Bad stream");
199
0
    return ERRCODE_NONE;
200
0
}
201
202
// virtual
203
ErrCode SvLockBytes::SetSize(sal_uInt64)
204
0
{
205
0
    OSL_FAIL("SvLockBytes::SetSize(): Bad stream");
206
0
    return ERRCODE_NONE;
207
0
}
208
209
ErrCode SvLockBytes::Stat(SvLockBytesStat *) const
210
0
{
211
0
    OSL_FAIL("SvLockBytes::Stat(): Bad stream");
212
0
    return ERRCODE_NONE;
213
0
}
214
215
216
std::size_t SvStream::GetData( void* pData, std::size_t nSize )
217
39.0M
{
218
39.0M
    if( !GetError() )
219
39.0M
    {
220
39.0M
        DBG_ASSERT( m_xLockBytes.is(), "pure virtual function" );
221
39.0M
        std::size_t nRet(0);
222
39.0M
        m_nError = m_xLockBytes->ReadAt(m_nActPos, pData, nSize, &nRet);
223
39.0M
        m_nActPos += nRet;
224
39.0M
        return nRet;
225
39.0M
    }
226
7.44k
    else return 0;
227
39.0M
}
228
229
std::size_t SvStream::PutData( const void* pData, std::size_t nSize )
230
560k
{
231
560k
    if( !GetError() )
232
560k
    {
233
560k
        DBG_ASSERT( m_xLockBytes.is(), "pure virtual function" );
234
560k
        std::size_t nRet(0);
235
560k
        m_nError = m_xLockBytes->WriteAt(m_nActPos, pData, nSize, &nRet);
236
560k
        m_nActPos += nRet;
237
560k
        return nRet;
238
560k
    }
239
0
    else return 0;
240
560k
}
241
242
sal_uInt64 SvStream::SeekPos(sal_uInt64 const nPos)
243
52.3M
{
244
    // check if a truncated STREAM_SEEK_TO_END was passed
245
52.3M
    assert(nPos != SAL_MAX_UINT32);
246
52.3M
    if( !GetError() && nPos == STREAM_SEEK_TO_END )
247
4.90M
    {
248
4.90M
        DBG_ASSERT( m_xLockBytes.is(), "pure virtual function" );
249
4.90M
        SvLockBytesStat aStat;
250
4.90M
        m_xLockBytes->Stat( &aStat );
251
4.90M
        m_nActPos = aStat.nSize;
252
4.90M
    }
253
47.4M
    else
254
47.4M
        m_nActPos = nPos;
255
52.3M
    return m_nActPos;
256
52.3M
}
257
258
void SvStream::FlushData()
259
470k
{
260
470k
    if( !GetError() )
261
460k
    {
262
460k
        DBG_ASSERT( m_xLockBytes.is(), "pure virtual function" );
263
460k
        m_nError = m_xLockBytes->Flush();
264
460k
    }
265
470k
}
266
267
void SvStream::SetSize(sal_uInt64 const nSize)
268
237k
{
269
237k
    DBG_ASSERT( m_xLockBytes.is(), "pure virtual function" );
270
237k
    m_nError = m_xLockBytes->SetSize( nSize );
271
237k
}
272
273
SvStream::SvStream() :
274
6.24M
     m_nActPos(0)
275
276
6.24M
   , m_pBufPos(nullptr)
277
6.24M
   , m_nBufSize(0)
278
6.24M
   , m_nBufActualLen(0)
279
6.24M
   , m_nBufActualPos(0)
280
6.24M
   , m_nBufFree(0)
281
6.24M
   , m_isIoRead(false)
282
6.24M
   , m_isIoWrite(false)
283
284
6.24M
   , m_isDirty(false)
285
6.24M
   , m_isEof(false)
286
287
6.24M
   , m_nCompressMode(SvStreamCompressFlags::NONE)
288
#if defined UNX
289
6.24M
   , m_eLineDelimiter(LINEEND_LF)   // UNIX-Format
290
#else
291
   , m_eLineDelimiter(LINEEND_CRLF) // DOS-Format
292
#endif
293
6.24M
   , m_eStreamEncoding(osl_getThreadTextEncoding())
294
295
6.24M
   , m_nCryptMask(0)
296
297
6.24M
   , m_nVersion(0)
298
299
6.24M
   , m_nBufFilePos(0)
300
6.24M
   , m_eStreamMode(StreamMode::NONE)
301
6.24M
   , m_isWritable(true)
302
303
6.24M
{
304
6.24M
    SetEndian( SvStreamEndian::LITTLE );
305
306
6.24M
    ClearError();
307
6.24M
}
308
309
232k
SvStream::SvStream( SvLockBytes* pLockBytesP ) : SvStream()
310
232k
{
311
232k
    m_xLockBytes = pLockBytesP;
312
232k
    SetBufferSize( 256 );
313
232k
}
314
315
SvStream::~SvStream()
316
6.24M
{
317
6.24M
    if (m_xLockBytes.is())
318
232k
        Flush();
319
6.24M
}
320
321
void SvStream::ClearError()
322
7.86M
{
323
7.86M
    m_isEof = false;
324
7.86M
    m_nError = ERRCODE_NONE;
325
7.86M
}
326
327
void SvStream::SetError( ErrCode nErrorCode )
328
141M
{
329
141M
    if (m_nError == ERRCODE_NONE || (m_nError.IsWarning() && nErrorCode.IsError()))
330
138M
        m_nError = nErrorCode;
331
141M
}
332
333
void SvStream::SetEndian( SvStreamEndian nNewFormat )
334
7.12M
{
335
#ifdef OSL_BIGENDIAN
336
    m_isSwap = nNewFormat == SvStreamEndian::LITTLE;
337
#else
338
7.12M
    m_isSwap = nNewFormat == SvStreamEndian::BIG;
339
7.12M
#endif
340
7.12M
}
341
342
SvStreamEndian SvStream::GetEndian() const
343
286k
{
344
#ifdef OSL_BIGENDIAN
345
    return m_isSwap ? SvStreamEndian::LITTLE : SvStreamEndian::BIG;
346
#else
347
286k
    return m_isSwap ? SvStreamEndian::BIG : SvStreamEndian::LITTLE;
348
286k
#endif
349
286k
}
350
351
void SvStream::SetBufferSize( sal_uInt16 nBufferSize )
352
7.66M
{
353
7.66M
    sal_uInt64 const nActualFilePos = Tell();
354
7.66M
    bool bDontSeek = (m_pRWBuf == nullptr);
355
356
7.66M
    if (m_isDirty && m_isWritable)  // due to Windows NT: Access denied
357
37.1k
        FlushBuffer();
358
359
7.66M
    if (m_nBufSize)
360
1.37M
    {
361
1.37M
        m_pRWBuf.reset();
362
1.37M
        m_nBufFilePos += m_nBufActualPos;
363
1.37M
    }
364
365
7.66M
    m_pRWBuf        = nullptr;
366
7.66M
    m_nBufActualLen = 0;
367
7.66M
    m_nBufActualPos = 0;
368
7.66M
    m_nBufSize      = nBufferSize;
369
7.66M
    if (m_nBufSize)
370
2.48M
        m_pRWBuf.reset(new sal_uInt8[ m_nBufSize ]);
371
7.66M
    m_pBufPos       = m_pRWBuf.get();
372
7.66M
    m_isIoRead = m_isIoWrite = false;
373
7.66M
    if( !bDontSeek )
374
1.37M
        SeekPos( nActualFilePos );
375
7.66M
}
376
377
void SvStream::ClearBuffer()
378
992k
{
379
992k
    m_nBufActualLen = 0;
380
992k
    m_nBufActualPos = 0;
381
992k
    m_nBufFilePos   = 0;
382
992k
    m_pBufPos       = m_pRWBuf.get();
383
992k
    m_isDirty       = false;
384
992k
    m_isIoRead = m_isIoWrite = false;
385
386
992k
    m_isEof         = false;
387
992k
}
388
389
void SvStream::ResetError()
390
276k
{
391
276k
    ClearError();
392
276k
}
393
394
bool SvStream::ReadByteStringLine( OUString& rStr, sal_Int32 nMaxBytesToRead )
395
2.34M
{
396
2.34M
    OStringBuffer aStr;
397
2.34M
    bool bRet = ReadLine( aStr, nMaxBytesToRead);
398
2.34M
    rStr = OStringToOUString(aStr, GetStreamEncoding());
399
2.34M
    return bRet;
400
2.34M
}
401
402
bool SvStream::ReadLine( OString& rStr, sal_Int32 nMaxBytesToRead )
403
186k
{
404
186k
    OStringBuffer aBuf(4096);
405
186k
    bool rv = ReadLine(aBuf, nMaxBytesToRead);
406
186k
    rStr = aBuf.makeStringAndClear();
407
186k
    return rv;
408
186k
}
409
410
bool SvStream::ReadLine( OStringBuffer& aBuf, sal_Int32 nMaxBytesToRead )
411
4.45M
{
412
4.45M
    char    buf[256+1];
413
4.45M
    bool        bEnd        = false;
414
4.45M
    sal_uInt64  nOldFilePos = Tell();
415
4.45M
    char    c           = 0;
416
4.45M
    std::size_t nTotalLen   = 0;
417
418
4.45M
    aBuf.setLength(0);
419
8.97M
    while( !bEnd && !GetError() )   // Don't test for EOF as we
420
                                    // are reading block-wise!
421
4.66M
    {
422
4.66M
        sal_uInt16 nLen = static_cast<sal_uInt16>(ReadBytes(buf, sizeof(buf)-1));
423
4.66M
        if ( !nLen )
424
141k
        {
425
141k
            if ( aBuf.isEmpty() )
426
73.9k
            {
427
                // Exit on first block-read error
428
73.9k
                m_isEof = true;
429
73.9k
                aBuf.setLength(0);
430
73.9k
                return false;
431
73.9k
            }
432
67.3k
            else
433
67.3k
                break;
434
141k
        }
435
436
4.51M
        sal_uInt16 j;
437
85.2M
        for( j = 0; j < nLen ; ++j )
438
84.9M
        {
439
84.9M
            if (nTotalLen + j >= o3tl::make_unsigned(nMaxBytesToRead))
440
15
            {
441
15
                bEnd = true;
442
15
                break;
443
15
            }
444
84.9M
            c = buf[j];
445
84.9M
            if ( c == '\n' || c == '\r' )
446
4.31M
            {
447
4.31M
                bEnd = true;
448
4.31M
                break;
449
4.31M
            }
450
84.9M
        }
451
4.51M
        nTotalLen += j;
452
4.51M
        if ( j )
453
3.73M
            aBuf.append(buf, j);
454
4.51M
    }
455
456
4.37M
    if ( !bEnd && !GetError() && !aBuf.isEmpty() )
457
67.3k
        bEnd = true;
458
459
4.37M
    nOldFilePos += nTotalLen;
460
4.37M
    if( Tell() > nOldFilePos )
461
4.31M
        nOldFilePos++;
462
4.37M
    Seek( nOldFilePos );  // Seek pointer due to BlockRead above
463
464
4.37M
    if ( bEnd && (c=='\r' || c=='\n') )  // Special treatment for DOS files
465
4.31M
    {
466
4.31M
        char cTemp;
467
4.31M
        std::size_t nLen = ReadBytes(&cTemp, sizeof(cTemp));
468
4.31M
        if ( nLen ) {
469
4.30M
            if( cTemp == c || (cTemp != '\n' && cTemp != '\r') )
470
4.18M
                Seek( nOldFilePos );
471
4.30M
        }
472
4.31M
    }
473
474
4.37M
    if ( bEnd )
475
4.37M
        m_isEof = false;
476
4.37M
    return bEnd;
477
4.45M
}
478
479
bool SvStream::ReadUniStringLine( OUString& rStr, sal_Int32 nMaxCodepointsToRead )
480
0
{
481
0
    sal_Unicode buf[256+1];
482
0
    bool        bEnd        = false;
483
0
    sal_uInt64  nOldFilePos = Tell();
484
0
    sal_Unicode c           = 0;
485
0
    std::size_t nTotalLen   = 0;
486
487
0
    DBG_ASSERT( sizeof(sal_Unicode) == sizeof(sal_uInt16), "ReadUniStringLine: swapping sizeof(sal_Unicode) not implemented" );
488
489
0
    OUStringBuffer aBuf(4096);
490
0
    while( !bEnd && !GetError() )   // Don't test for EOF as we
491
                                    // are reading block-wise!
492
0
    {
493
0
        sal_uInt16 nLen = static_cast<sal_uInt16>(ReadBytes( buf, sizeof(buf)-sizeof(sal_Unicode)));
494
0
        nLen /= sizeof(sal_Unicode);
495
0
        if ( !nLen )
496
0
        {
497
0
            if ( aBuf.isEmpty() )
498
0
            {
499
                // exit on first BlockRead error
500
0
                m_isEof = true;
501
0
                rStr.clear();
502
0
                return false;
503
0
            }
504
0
            else
505
0
                break;
506
0
        }
507
508
0
        sal_uInt16 j;
509
0
        for( j = 0; j < nLen ; ++j )
510
0
        {
511
0
            if (nTotalLen + j >= o3tl::make_unsigned(nMaxCodepointsToRead))
512
0
            {
513
0
                bEnd = true;
514
0
                break;
515
0
            }
516
0
            if (m_isSwap)
517
0
                SwapNumber( buf[j] );
518
0
            c = buf[j];
519
0
            if ( c == '\n' || c == '\r' )
520
0
            {
521
0
                bEnd = true;
522
0
                break;
523
0
            }
524
0
        }
525
0
        nTotalLen += j;
526
0
        if ( j )
527
0
            aBuf.append( buf, j );
528
0
    }
529
530
0
    if ( !bEnd && !GetError() && !aBuf.isEmpty() )
531
0
        bEnd = true;
532
533
0
    nOldFilePos += nTotalLen * sizeof(sal_Unicode);
534
0
    if( Tell() > nOldFilePos )
535
0
        nOldFilePos += sizeof(sal_Unicode);
536
0
    Seek( nOldFilePos );  // seek due to BlockRead above
537
538
0
    if ( bEnd && (c=='\r' || c=='\n') )  // special treatment for DOS files
539
0
    {
540
0
        sal_Unicode cTemp;
541
0
        ReadBytes( &cTemp, sizeof(cTemp) );
542
0
        if (m_isSwap)
543
0
            SwapNumber( cTemp );
544
0
        if( cTemp == c || (cTemp != '\n' && cTemp != '\r') )
545
0
            Seek( nOldFilePos );
546
0
    }
547
548
0
    if ( bEnd )
549
0
        m_isEof = false;
550
0
    rStr = aBuf.makeStringAndClear();
551
0
    return bEnd;
552
0
}
553
554
bool SvStream::ReadUniOrByteStringLine( OUString& rStr,
555
                                        sal_Int32 nMaxCodepointsToRead )
556
2.34M
{
557
2.34M
    auto eSrcEncoding = GetStreamEncoding();
558
2.34M
    if (eSrcEncoding == RTL_TEXTENCODING_UNICODE)
559
0
        return ReadUniStringLine( rStr, nMaxCodepointsToRead );
560
2.34M
    else
561
2.34M
        return ReadByteStringLine(rStr, nMaxCodepointsToRead);
562
2.34M
}
563
564
OString read_zeroTerminated_uInt8s_ToOString(SvStream& rStream)
565
370k
{
566
370k
    OStringBuffer aOutput(256);
567
568
370k
    char buf[ 256 + 1 ];
569
370k
    bool bEnd = false;
570
370k
    sal_uInt64 nFilePos = rStream.Tell();
571
572
745k
    while( !bEnd && !rStream.GetError() )
573
375k
    {
574
375k
        std::size_t nLen = rStream.ReadBytes(buf, sizeof(buf)-1);
575
375k
        if (!nLen)
576
382
            break;
577
578
374k
        std::size_t nReallyRead = nLen;
579
374k
        const char* pPtr = buf;
580
3.52M
        while (nLen && *pPtr)
581
3.15M
        {
582
3.15M
            ++pPtr;
583
3.15M
            --nLen;
584
3.15M
        }
585
586
374k
        bEnd =  ( nReallyRead < sizeof(buf)-1 )         // read less than attempted to read
587
314k
                ||  (  ( nLen > 0 )                    // OR it is inside the block we read
588
310k
                    &&  ( 0 == *pPtr )                  //    AND found a string terminator
589
314k
                    );
590
591
374k
        aOutput.append(buf, pPtr - buf);
592
374k
    }
593
594
370k
    nFilePos += aOutput.getLength();
595
370k
    if (rStream.Tell() > nFilePos)
596
369k
        rStream.Seek(nFilePos+1);  // seek due to FileRead above
597
370k
    return aOutput.makeStringAndClear();
598
370k
}
599
600
OUString read_zeroTerminated_uInt8s_ToOUString(SvStream& rStream, rtl_TextEncoding eEnc)
601
258k
{
602
258k
    return OStringToOUString(
603
258k
        read_zeroTerminated_uInt8s_ToOString(rStream), eEnc);
604
258k
}
605
606
/** Attempt to write a sequence of nUnits 16bit units from an OUString,
607
    returned value is number of bytes written */
608
static std::size_t write_uInt16s_FromOUString(SvStream& rStrm, std::u16string_view rStr,
609
    std::size_t nUnits)
610
107k
{
611
107k
    DBG_ASSERT( sizeof(sal_Unicode) == sizeof(sal_uInt16), "write_uInt16s_FromOUString: swapping sizeof(sal_Unicode) not implemented" );
612
107k
    std::size_t nWritten;
613
107k
    if (!rStrm.IsEndianSwap())
614
107k
        nWritten = rStrm.WriteBytes(rStr.data(), nUnits * sizeof(sal_Unicode));
615
0
    else
616
0
    {
617
0
        std::size_t nLen = nUnits;
618
0
        sal_Unicode aBuf[384];
619
0
        sal_Unicode* const pTmp = ( nLen > 384 ? new sal_Unicode[nLen] : aBuf);
620
0
        memcpy( pTmp, rStr.data(), nLen * sizeof(sal_Unicode) );
621
0
        sal_Unicode* p = pTmp;
622
0
        const sal_Unicode* const pStop = pTmp + nLen;
623
0
        while ( p < pStop )
624
0
        {
625
0
            SwapNumber( *p );
626
0
            p++;
627
0
        }
628
0
        nWritten = rStrm.WriteBytes( pTmp, nLen * sizeof(sal_Unicode) );
629
0
        if ( pTmp != aBuf )
630
0
            delete [] pTmp;
631
0
    }
632
107k
    return nWritten;
633
107k
}
634
635
bool SvStream::WriteUnicodeOrByteText(std::u16string_view rStr, rtl_TextEncoding eDestEncoding, bool bZero)
636
106k
{
637
106k
    if (eDestEncoding == RTL_TEXTENCODING_UNICODE)
638
106k
    {
639
106k
        write_uInt16s_FromOUString(*this, rStr, rStr.size());
640
106k
        if (bZero)
641
0
            WriteUnicode(0);
642
106k
    }
643
0
    else
644
0
    {
645
0
        OString aStr(OUStringToOString(rStr, eDestEncoding));
646
0
        WriteBytes(aStr.getStr(), aStr.getLength());
647
0
        if (bZero)
648
0
            WriteChar(0);
649
0
    }
650
106k
    return m_nError == ERRCODE_NONE;
651
106k
}
652
653
bool SvStream::WriteByteStringLine( std::u16string_view rStr )
654
0
{
655
0
    return WriteLine(OUStringToOString(rStr, GetStreamEncoding()));
656
0
}
657
658
bool SvStream::WriteLine(std::string_view rStr)
659
0
{
660
0
    WriteBytes(rStr.data(), rStr.size());
661
0
    endl(*this);
662
0
    return m_nError == ERRCODE_NONE;
663
0
}
664
665
bool SvStream::WriteUniOrByteChar(sal_Unicode ch)
666
0
{
667
0
    auto eDestEncoding = GetStreamEncoding();
668
0
    if (eDestEncoding == RTL_TEXTENCODING_UNICODE)
669
0
        WriteUnicode(ch);
670
0
    else
671
0
    {
672
0
        OString aStr(&ch, 1, eDestEncoding);
673
0
        WriteBytes(aStr.getStr(), aStr.getLength());
674
0
    }
675
0
    return m_nError == ERRCODE_NONE;
676
0
}
677
678
void SvStream::StartWritingUnicodeText()
679
0
{
680
0
    ResetEndianSwap(); // Switch to no endian swapping
681
    // BOM, Byte Order Mark, U+FEFF, see
682
    // http://www.unicode.org/faq/utf_bom.html#BOM
683
    // Upon read: 0xfeff(-257) => no swap; 0xfffe(-2) => swap
684
0
    WriteUInt16(0xfeff);
685
0
}
686
687
void SvStream::StartReadingUnicodeText(rtl_TextEncoding eReadBomEncoding)
688
53.5k
{
689
53.5k
    if (!(  eReadBomEncoding == RTL_TEXTENCODING_DONTKNOW ||
690
9.10k
            eReadBomEncoding == RTL_TEXTENCODING_UNICODE ||
691
9.10k
            eReadBomEncoding == RTL_TEXTENCODING_UTF8))
692
9.10k
        return;    // nothing to read
693
694
44.4k
    const sal_uInt64 nOldPos = Tell();
695
44.4k
    unsigned char nFlag(0);
696
44.4k
    ReadUChar( nFlag );
697
44.4k
    switch ( nFlag )
698
44.4k
    {
699
57
        case 0xfe: // UTF-16BE?
700
57
            if (    eReadBomEncoding == RTL_TEXTENCODING_DONTKNOW ||
701
0
                    eReadBomEncoding == RTL_TEXTENCODING_UNICODE)
702
57
            {
703
57
                ReadUChar(nFlag);
704
57
                if (nFlag == 0xff)
705
7
                {
706
7
                    SetStreamEncoding(RTL_TEXTENCODING_UNICODE);
707
7
                    SetEndian(SvStreamEndian::BIG);
708
7
                    return;
709
7
                }
710
57
            }
711
50
        break;
712
168
        case 0xff: // UTF-16LE?
713
168
            if (    eReadBomEncoding == RTL_TEXTENCODING_DONTKNOW ||
714
0
                    eReadBomEncoding == RTL_TEXTENCODING_UNICODE)
715
168
            {
716
168
                ReadUChar(nFlag);
717
168
                if (nFlag == 0xfe)
718
25
                {
719
25
                    SetStreamEncoding(RTL_TEXTENCODING_UNICODE);
720
25
                    SetEndian(SvStreamEndian::LITTLE);
721
25
                    return;
722
25
                }
723
168
            }
724
143
        break;
725
143
        case 0xef: // UTF-8?
726
131
            if (    eReadBomEncoding == RTL_TEXTENCODING_DONTKNOW ||
727
0
                    eReadBomEncoding == RTL_TEXTENCODING_UTF8)
728
131
            {
729
131
                ReadUChar(nFlag);
730
131
                if (nFlag == 0xbb)
731
70
                {
732
70
                    ReadUChar(nFlag);
733
70
                    if (nFlag == 0xbf)
734
63
                    {
735
63
                        SetStreamEncoding(RTL_TEXTENCODING_UTF8);
736
63
                        return;
737
63
                    }
738
70
                }
739
131
            }
740
68
        break;
741
44.0k
        default:
742
44.0k
            ;   // nothing
743
44.4k
    }
744
44.3k
    Seek(nOldPos); // no BOM, pure data
745
44.3k
}
746
747
void SvStream::DetectEncoding(size_t maxBytes)
748
44.4k
{
749
44.4k
    static constexpr auto mapEncodings
750
44.4k
        = frozen::make_unordered_map<std::string_view, rtl_TextEncoding>({
751
44.4k
            { "UTF-8", RTL_TEXTENCODING_UTF8 },
752
44.4k
            { "UTF-16BE", RTL_TEXTENCODING_UCS2 },
753
44.4k
            { "UTF-16LE", RTL_TEXTENCODING_UCS2 },
754
            //{ "UTF-32BE", RTL_TEXTENCODING_UCS4 },
755
            //{ "UTF-32LE", RTL_TEXTENCODING_UCS4 },
756
44.4k
            { "Shift_JIS", RTL_TEXTENCODING_SHIFT_JIS },
757
44.4k
            { "ISO-2022-JP", RTL_TEXTENCODING_ISO_2022_JP },
758
44.4k
            { "ISO-2022-CN", RTL_TEXTENCODING_ISO_2022_CN },
759
44.4k
            { "ISO-2022-KR", RTL_TEXTENCODING_ISO_2022_KR },
760
44.4k
            { "GB18030", RTL_TEXTENCODING_GB_18030 },
761
44.4k
            { "Big5", RTL_TEXTENCODING_BIG5 },
762
44.4k
            { "EUC-JP", RTL_TEXTENCODING_EUC_JP },
763
44.4k
            { "EUC-KR", RTL_TEXTENCODING_EUC_KR },
764
44.4k
            { "ISO-8859-1", RTL_TEXTENCODING_ISO_8859_1 },
765
44.4k
            { "ISO-8859-2", RTL_TEXTENCODING_ISO_8859_2 },
766
44.4k
            { "ISO-8859-5", RTL_TEXTENCODING_ISO_8859_5 },
767
44.4k
            { "ISO-8859-6", RTL_TEXTENCODING_ISO_8859_6 },
768
44.4k
            { "ISO-8859-7", RTL_TEXTENCODING_ISO_8859_7 },
769
44.4k
            { "ISO-8859-8", RTL_TEXTENCODING_ISO_8859_8 },
770
            // for tdf#171097 (see https://en.wikipedia.org/wiki/ISO-8859-8-I)
771
44.4k
            { "ISO-8859-8-I", RTL_TEXTENCODING_ISO_8859_8 },
772
44.4k
            { "ISO-8859-9", RTL_TEXTENCODING_ISO_8859_9 },
773
44.4k
            { "windows-1250", RTL_TEXTENCODING_MS_1250 },
774
44.4k
            { "windows-1251", RTL_TEXTENCODING_MS_1251 },
775
44.4k
            { "windows-1252", RTL_TEXTENCODING_MS_1252 },
776
44.4k
            { "windows-1253", RTL_TEXTENCODING_MS_1253 },
777
44.4k
            { "windows-1254", RTL_TEXTENCODING_MS_1254 },
778
44.4k
            { "windows-1255", RTL_TEXTENCODING_MS_1255 },
779
44.4k
            { "windows-1256", RTL_TEXTENCODING_MS_1256 },
780
44.4k
            { "KOI8-R", RTL_TEXTENCODING_KOI8_R },
781
44.4k
        });
782
783
44.4k
    const sal_uInt64 nOrigPos = Tell();
784
44.4k
    SetStreamEncoding(RTL_TEXTENCODING_DONTKNOW);
785
44.4k
    StartReadingUnicodeText(RTL_TEXTENCODING_DONTKNOW);
786
44.4k
    if (!good())
787
0
        return;
788
44.4k
    if (GetStreamEncoding() != RTL_TEXTENCODING_DONTKNOW)
789
95
        return; // BOM detected, encoding already set
790
791
44.4k
    assert(Tell() - nOrigPos == 0); // we are at nOrigPos
792
44.3k
    auto bytes = std::make_unique<char[]>(maxBytes);
793
44.3k
    size_t nRead = ReadBytes(bytes.get(), maxBytes);
794
44.3k
    Seek(nOrigPos);
795
44.3k
    ResetError();
796
797
44.3k
    if (nRead == 0)
798
0
        return;
799
800
44.3k
    UErrorCode uerr = U_ZERO_ERROR;
801
44.3k
    UCharsetDetector* ucd = ucsdet_open(&uerr);
802
44.3k
    if (!U_SUCCESS(uerr))
803
0
        return;
804
44.3k
    comphelper::ScopeGuard ucsdet_close_guard([ucd] { ucsdet_close(ucd); });
805
806
44.3k
    ucsdet_setText(ucd, bytes.get(), nRead, &uerr);
807
44.3k
    if (!U_SUCCESS(uerr))
808
0
        return;
809
810
44.3k
    int32_t matchCount = 0;
811
44.3k
    const UCharsetMatch **matches = ucsdet_detectAll(ucd, &matchCount, &uerr);
812
44.3k
    if (!U_SUCCESS(uerr))
813
149
        return;
814
815
44.2k
    static constexpr std::array<std::string_view, 5> aSkipCharsets = {
816
44.2k
    "UTF-16BE",
817
44.2k
    "UTF-16LE",
818
44.2k
    "Shift_JIS",
819
44.2k
    "GB18030",
820
44.2k
    "Big5"
821
44.2k
    };
822
44.2k
    SAL_INFO("tools.stream", "The first character set of the following list will be used or the function will return");
823
824
    // by default, let's use the first character set detected
825
44.2k
    const UCharsetMatch* match = matches[0];
826
44.2k
    constexpr int CONFIDENCE_MIN_SKIP_CHARSETS = 10;
827
46.3k
    for (int i=0; i < matchCount; i++)
828
46.1k
    {
829
46.1k
        const char* pName = ucsdet_getName(matches[i], &uerr);
830
46.1k
        int confidence = ucsdet_getConfidence(matches[i], &uerr);
831
46.1k
        SAL_INFO("tools.stream",
832
46.1k
                "\tcharacter set name=" << pName
833
46.1k
                << " has a confidence of " << confidence);
834
46.1k
        if (confidence == CONFIDENCE_MIN_SKIP_CHARSETS &&
835
2.50k
             std::find(aSkipCharsets.begin(), aSkipCharsets.end(), pName) != aSkipCharsets.end())
836
2.09k
        {
837
2.09k
            continue;
838
2.09k
        }
839
44.0k
        match = matches[i];
840
44.0k
        break;
841
46.1k
    }
842
843
44.2k
    const char* pEncodingName = ucsdet_getName(match, &uerr);
844
44.2k
    if (!U_SUCCESS(uerr) || !pEncodingName)
845
0
        return;
846
847
44.2k
    const auto it = mapEncodings.find(pEncodingName);
848
44.2k
    if (it == mapEncodings.end())
849
298
        return;
850
851
43.9k
    rtl_TextEncoding eEncoding = it->second;
852
43.9k
    SetStreamEncoding(eEncoding);
853
43.9k
    if (eEncoding == RTL_TEXTENCODING_UCS2)
854
891
    {
855
891
        if (it->first == "UTF-16LE")
856
594
            SetEndian(SvStreamEndian::LITTLE);
857
297
        else if (it->first == "UTF-16BE")
858
297
            SetEndian(SvStreamEndian::BIG);
859
891
    }
860
43.9k
}
861
862
sal_uInt64 SvStream::SeekRel(sal_Int64 const nPos)
863
59.6M
{
864
59.6M
    sal_uInt64 nActualPos = Tell();
865
866
59.6M
    if ( nPos >= 0 )
867
16.0M
    {
868
16.0M
        if (SAL_MAX_UINT64 - nActualPos > o3tl::make_unsigned(nPos))
869
16.0M
            nActualPos += nPos;
870
16.0M
    }
871
43.6M
    else
872
43.6M
    {
873
43.6M
        sal_uInt64 const nAbsPos = static_cast<sal_uInt64>(-nPos);
874
43.6M
        if ( nActualPos >= nAbsPos )
875
43.6M
            nActualPos -= nAbsPos;
876
43.6M
    }
877
878
59.6M
    assert((m_pBufPos != nullptr) == bool(m_pRWBuf));
879
59.6M
    if (m_pRWBuf)
880
46.3M
    {
881
46.3M
        m_pBufPos = m_pRWBuf.get() + nActualPos;
882
46.3M
    }
883
59.6M
    return Seek( nActualPos );
884
59.6M
}
885
886
template <typename T> SvStream& SvStream::ReadNumber(T& r)
887
386M
{
888
386M
    T n = 0;
889
386M
    readNumberWithoutSwap(n);
890
386M
    if (good())
891
307M
    {
892
307M
        if (m_isSwap)
893
12.9M
            SwapNumber(n);
894
307M
        r = n;
895
307M
    }
896
386M
    return *this;
897
386M
}
SvStream& SvStream::ReadNumber<unsigned short>(unsigned short&)
Line
Count
Source
887
112M
{
888
112M
    T n = 0;
889
112M
    readNumberWithoutSwap(n);
890
112M
    if (good())
891
88.8M
    {
892
88.8M
        if (m_isSwap)
893
48.6k
            SwapNumber(n);
894
88.8M
        r = n;
895
88.8M
    }
896
112M
    return *this;
897
112M
}
SvStream& SvStream::ReadNumber<unsigned int>(unsigned int&)
Line
Count
Source
887
61.7M
{
888
61.7M
    T n = 0;
889
61.7M
    readNumberWithoutSwap(n);
890
61.7M
    if (good())
891
61.0M
    {
892
61.0M
        if (m_isSwap)
893
12.0M
            SwapNumber(n);
894
61.0M
        r = n;
895
61.0M
    }
896
61.7M
    return *this;
897
61.7M
}
Unexecuted instantiation: SvStream& SvStream::ReadNumber<unsigned long>(unsigned long&)
SvStream& SvStream::ReadNumber<short>(short&)
Line
Count
Source
887
20.6M
{
888
20.6M
    T n = 0;
889
20.6M
    readNumberWithoutSwap(n);
890
20.6M
    if (good())
891
7.51M
    {
892
7.51M
        if (m_isSwap)
893
73.5k
            SwapNumber(n);
894
7.51M
        r = n;
895
7.51M
    }
896
20.6M
    return *this;
897
20.6M
}
SvStream& SvStream::ReadNumber<int>(int&)
Line
Count
Source
887
119M
{
888
119M
    T n = 0;
889
119M
    readNumberWithoutSwap(n);
890
119M
    if (good())
891
77.0M
    {
892
77.0M
        if (m_isSwap)
893
6.29k
            SwapNumber(n);
894
77.0M
        r = n;
895
77.0M
    }
896
119M
    return *this;
897
119M
}
Unexecuted instantiation: SvStream& SvStream::ReadNumber<long>(long&)
SvStream& SvStream::ReadNumber<char16_t>(char16_t&)
Line
Count
Source
887
72.8M
{
888
72.8M
    T n = 0;
889
72.8M
    readNumberWithoutSwap(n);
890
72.8M
    if (good())
891
72.8M
    {
892
72.8M
        if (m_isSwap)
893
773k
            SwapNumber(n);
894
72.8M
        r = n;
895
72.8M
    }
896
72.8M
    return *this;
897
72.8M
}
898
899
112M
SvStream& SvStream::ReadUInt16(sal_uInt16& r) { return ReadNumber(r); }
900
61.7M
SvStream& SvStream::ReadUInt32(sal_uInt32& r) { return ReadNumber(r); }
901
0
SvStream& SvStream::ReadUInt64(sal_uInt64& r) { return ReadNumber(r); }
902
20.6M
SvStream& SvStream::ReadInt16(sal_Int16& r) { return ReadNumber(r); }
903
119M
SvStream& SvStream::ReadInt32(sal_Int32& r) { return ReadNumber(r); }
904
0
SvStream& SvStream::ReadInt64(sal_Int64& r) { return ReadNumber(r); }
905
906
SvStream& SvStream::ReadSChar( signed char& r )
907
8.52M
{
908
8.52M
    if (m_isIoRead && sizeof(signed char) <= m_nBufFree)
909
8.39M
    {
910
8.39M
        r = *m_pBufPos;
911
8.39M
        m_nBufActualPos += sizeof(signed char);
912
8.39M
        m_pBufPos += sizeof(signed char);
913
8.39M
        m_nBufFree -= sizeof(signed char);
914
8.39M
    }
915
131k
    else
916
131k
        ReadBytes( &r, sizeof(signed char) );
917
8.52M
    return *this;
918
8.52M
}
919
920
// Special treatment for Chars due to PutBack
921
922
SvStream& SvStream::ReadChar( char& r )
923
233M
{
924
233M
    if (m_isIoRead && sizeof(char) <= m_nBufFree)
925
103M
    {
926
103M
        r = *m_pBufPos;
927
103M
        m_nBufActualPos += sizeof(char);
928
103M
        m_pBufPos += sizeof(char);
929
103M
        m_nBufFree -= sizeof(char);
930
103M
    }
931
130M
    else
932
130M
        ReadBytes( &r, sizeof(char) );
933
233M
    return *this;
934
233M
}
935
936
SvStream& SvStream::ReadUChar( unsigned char& r )
937
239M
{
938
239M
    if (m_isIoRead && sizeof(char) <= m_nBufFree)
939
54.0M
    {
940
54.0M
        r = *m_pBufPos;
941
54.0M
        m_nBufActualPos += sizeof(char);
942
54.0M
        m_pBufPos += sizeof(char);
943
54.0M
        m_nBufFree -= sizeof(char);
944
54.0M
    }
945
185M
    else
946
185M
        ReadBytes( &r, sizeof(char) );
947
239M
    return *this;
948
239M
}
949
950
72.8M
SvStream& SvStream::ReadUtf16(sal_Unicode& r) { return ReadNumber(r); }
951
952
SvStream& SvStream::ReadCharAsBool( bool& r )
953
4.80k
{
954
4.80k
    if (m_isIoRead && sizeof(char) <= m_nBufFree)
955
4.59k
    {
956
4.59k
        SAL_WARN_IF(
957
4.59k
            *m_pBufPos > 1, "tools.stream", unsigned(*m_pBufPos) << " not 0/1");
958
4.59k
        r = *m_pBufPos != 0;
959
4.59k
        m_nBufActualPos += sizeof(char);
960
4.59k
        m_pBufPos += sizeof(char);
961
4.59k
        m_nBufFree -= sizeof(char);
962
4.59k
    }
963
207
    else
964
207
    {
965
207
        unsigned char c;
966
207
        if (ReadBytes(&c, 1) == 1)
967
207
        {
968
207
            SAL_WARN_IF(c > 1, "tools.stream", unsigned(c) << " not 0/1");
969
207
            r = c != 0;
970
207
        }
971
207
    }
972
4.80k
    return *this;
973
4.80k
}
974
975
SvStream& SvStream::ReadFloat(float& r)
976
557k
{
977
557k
    float n = 0;
978
557k
    readNumberWithoutSwap(n);
979
557k
    if (good())
980
553k
    {
981
553k
#if defined UNX
982
553k
        if (m_isSwap)
983
0
          SwapFloat(n);
984
553k
#endif
985
553k
        r = n;
986
553k
    }
987
557k
    return *this;
988
557k
}
989
990
SvStream& SvStream::ReadDouble(double& r)
991
1.74M
{
992
1.74M
    double n = 0;
993
1.74M
    readNumberWithoutSwap(n);
994
1.74M
    if (good())
995
1.72M
    {
996
1.72M
#if defined UNX
997
1.72M
        if (m_isSwap)
998
0
          SwapDouble(n);
999
1.72M
#endif
1000
1.72M
        r = n;
1001
1.72M
    }
1002
1.74M
    return *this;
1003
1.74M
}
1004
1005
SvStream& SvStream::ReadStream( SvStream& rStream )
1006
273
{
1007
273
    const sal_uInt32 cBufLen = 0x8000;
1008
273
    std::unique_ptr<char[]> pBuf( new char[ cBufLen ] );
1009
1010
273
    sal_uInt32 nCount;
1011
309
    do {
1012
309
        nCount = ReadBytes( pBuf.get(), cBufLen );
1013
309
        rStream.WriteBytes( pBuf.get(), nCount );
1014
309
    } while( nCount == cBufLen );
1015
1016
273
    return *this;
1017
273
}
1018
1019
template <typename T> SvStream& SvStream::WriteNumber(T n)
1020
76.0M
{
1021
76.0M
    if (m_isSwap)
1022
222k
        SwapNumber(n);
1023
76.0M
    writeNumberWithoutSwap(n);
1024
76.0M
    return *this;
1025
76.0M
}
SvStream& SvStream::WriteNumber<unsigned short>(unsigned short)
Line
Count
Source
1020
44.8M
{
1021
44.8M
    if (m_isSwap)
1022
0
        SwapNumber(n);
1023
44.8M
    writeNumberWithoutSwap(n);
1024
44.8M
    return *this;
1025
44.8M
}
SvStream& SvStream::WriteNumber<unsigned int>(unsigned int)
Line
Count
Source
1020
2.51M
{
1021
2.51M
    if (m_isSwap)
1022
204k
        SwapNumber(n);
1023
2.51M
    writeNumberWithoutSwap(n);
1024
2.51M
    return *this;
1025
2.51M
}
SvStream& SvStream::WriteNumber<unsigned long>(unsigned long)
Line
Count
Source
1020
18.1k
{
1021
18.1k
    if (m_isSwap)
1022
18.1k
        SwapNumber(n);
1023
18.1k
    writeNumberWithoutSwap(n);
1024
18.1k
    return *this;
1025
18.1k
}
SvStream& SvStream::WriteNumber<short>(short)
Line
Count
Source
1020
372k
{
1021
372k
    if (m_isSwap)
1022
0
        SwapNumber(n);
1023
372k
    writeNumberWithoutSwap(n);
1024
372k
    return *this;
1025
372k
}
SvStream& SvStream::WriteNumber<int>(int)
Line
Count
Source
1020
28.2M
{
1021
28.2M
    if (m_isSwap)
1022
0
        SwapNumber(n);
1023
28.2M
    writeNumberWithoutSwap(n);
1024
28.2M
    return *this;
1025
28.2M
}
Unexecuted instantiation: SvStream& SvStream::WriteNumber<long>(long)
1026
1027
44.8M
SvStream& SvStream::WriteUInt16(sal_uInt16 v) { return WriteNumber(v); }
1028
2.51M
SvStream& SvStream::WriteUInt32(sal_uInt32 v) { return WriteNumber(v); }
1029
18.1k
SvStream& SvStream::WriteUInt64(sal_uInt64 v) { return WriteNumber(v); }
1030
372k
SvStream& SvStream::WriteInt16(sal_Int16 v) { return WriteNumber(v); }
1031
28.2M
SvStream& SvStream::WriteInt32(sal_Int32 v) { return WriteNumber(v); }
1032
0
SvStream& SvStream::WriteInt64(sal_Int64 v) { return WriteNumber(v); }
1033
1034
SvStream& SvStream::WriteSChar( signed char v )
1035
0
{
1036
    //SDO
1037
0
    if (m_isIoWrite && sizeof(signed char) <= m_nBufFree)
1038
0
    {
1039
0
        *m_pBufPos = v;
1040
0
        m_pBufPos++; // sizeof(char);
1041
0
        m_nBufActualPos++;
1042
0
        if (m_nBufActualPos > m_nBufActualLen)  // Append ?
1043
0
            m_nBufActualLen = m_nBufActualPos;
1044
0
        m_nBufFree--; // = sizeof(char);
1045
0
        m_isDirty = true;
1046
0
    }
1047
0
    else
1048
0
        WriteBytes( &v, sizeof(signed char) );
1049
0
    return *this;
1050
0
}
1051
1052
// Special treatment for Chars due to PutBack
1053
1054
SvStream& SvStream::WriteChar( char v )
1055
47.9k
{
1056
    //SDO
1057
47.9k
    if (m_isIoWrite && sizeof(char) <= m_nBufFree)
1058
47.1k
    {
1059
47.1k
        *m_pBufPos = v;
1060
47.1k
        m_pBufPos++; // sizeof(char);
1061
47.1k
        m_nBufActualPos++;
1062
47.1k
        if (m_nBufActualPos > m_nBufActualLen)  // Append ?
1063
47.1k
            m_nBufActualLen = m_nBufActualPos;
1064
47.1k
        m_nBufFree--; // = sizeof(char);
1065
47.1k
        m_isDirty = true;
1066
47.1k
    }
1067
870
    else
1068
870
        WriteBytes( &v, sizeof(char) );
1069
47.9k
    return *this;
1070
47.9k
}
1071
1072
SvStream& SvStream::WriteUChar( unsigned char v )
1073
13.7M
{
1074
//SDO
1075
13.7M
    if (m_isIoWrite && sizeof(char) <= m_nBufFree)
1076
1.03M
    {
1077
1.03M
        *reinterpret_cast<unsigned char*>(m_pBufPos) = v;
1078
1.03M
        m_pBufPos++; // = sizeof(char);
1079
1.03M
        m_nBufActualPos++; // = sizeof(char);
1080
1.03M
        if (m_nBufActualPos > m_nBufActualLen)  // Append ?
1081
1.03M
            m_nBufActualLen = m_nBufActualPos;
1082
1.03M
        m_nBufFree--;
1083
1.03M
        m_isDirty = true;
1084
1.03M
    }
1085
12.7M
    else
1086
12.7M
        WriteBytes( &v, sizeof(char) );
1087
13.7M
    return *this;
1088
13.7M
}
1089
1090
SvStream& SvStream::WriteUInt8( sal_uInt8 v )
1091
0
{
1092
0
    return WriteUChar(v);
1093
0
}
1094
1095
SvStream& SvStream::WriteUnicode( sal_Unicode v )
1096
0
{
1097
0
    return WriteUInt16(v);
1098
0
}
1099
1100
SvStream& SvStream::WriteFloat( float v )
1101
6.04k
{
1102
6.04k
#ifdef UNX
1103
6.04k
    if (m_isSwap)
1104
0
      SwapFloat(v);
1105
6.04k
#endif
1106
6.04k
    writeNumberWithoutSwap(v);
1107
6.04k
    return *this;
1108
6.04k
}
1109
1110
SvStream& SvStream::WriteDouble ( double v )
1111
40.0k
{
1112
40.0k
#if defined UNX
1113
40.0k
    if (m_isSwap)
1114
0
        SwapDouble(v);
1115
40.0k
#endif
1116
40.0k
    writeNumberWithoutSwap(v);
1117
40.0k
    return *this;
1118
40.0k
}
1119
1120
SvStream& SvStream::WriteStream( SvStream& rStream )
1121
10.0k
{
1122
10.0k
    const sal_uInt32 cBufLen = 0x8000;
1123
10.0k
    std::unique_ptr<char[]> pBuf( new char[ cBufLen ] );
1124
10.0k
    sal_uInt32 nCount;
1125
12.7k
    do {
1126
12.7k
        nCount = rStream.ReadBytes( pBuf.get(), cBufLen );
1127
12.7k
        WriteBytes( pBuf.get(), nCount );
1128
12.7k
    } while( nCount == cBufLen );
1129
1130
10.0k
    return *this;
1131
10.0k
}
1132
1133
sal_uInt64 SvStream::WriteStream( SvStream& rStream, sal_uInt64 nSize )
1134
23.8k
{
1135
23.8k
    const sal_uInt32 cBufLen = 0x8000;
1136
23.8k
    std::unique_ptr<char[]> pBuf( new char[ cBufLen ] );
1137
23.8k
    sal_uInt32 nCurBufLen = cBufLen;
1138
23.8k
    sal_uInt32 nCount;
1139
23.8k
    sal_uInt64 nWriteSize = nSize;
1140
1141
23.8k
    do
1142
24.5k
    {
1143
24.5k
        nCurBufLen = std::min<sal_uInt64>(nCurBufLen, nWriteSize);
1144
24.5k
        nCount = rStream.ReadBytes(pBuf.get(), nCurBufLen);
1145
24.5k
        WriteBytes( pBuf.get(), nCount );
1146
24.5k
        nWriteSize -= nCount;
1147
24.5k
    }
1148
24.5k
    while( nWriteSize && nCount == nCurBufLen );
1149
1150
23.8k
    return nSize - nWriteSize;
1151
23.8k
}
1152
1153
OUString SvStream::ReadUniOrByteString()
1154
1.35k
{
1155
1.35k
    return ReadUniOrByteString(GetStreamEncoding());
1156
1.35k
}
1157
1158
OUString SvStream::ReadUniOrByteString(rtl_TextEncoding eSrcEncoding)
1159
2.02k
{
1160
    // read UTF-16 string directly from stream ?
1161
2.02k
    if (eSrcEncoding == RTL_TEXTENCODING_UNICODE)
1162
675
        return read_uInt32_lenPrefixed_uInt16s_ToOUString(*this);
1163
1.35k
    return read_uInt16_lenPrefixed_uInt8s_ToOUString(*this, eSrcEncoding);
1164
2.02k
}
1165
1166
SvStream& SvStream::WriteUniOrByteString(std::u16string_view rStr)
1167
1.35k
{
1168
1.35k
    return WriteUniOrByteString(rStr, GetStreamEncoding());
1169
1.35k
}
1170
1171
SvStream& SvStream::WriteUniOrByteString(std::u16string_view rStr, rtl_TextEncoding eDestEncoding)
1172
2.02k
{
1173
    // write UTF-16 string directly into stream ?
1174
2.02k
    if (eDestEncoding == RTL_TEXTENCODING_UNICODE)
1175
675
        write_uInt32_lenPrefixed_uInt16s_FromOUString(*this, rStr);
1176
1.35k
    else
1177
1.35k
        write_uInt16_lenPrefixed_uInt8s_FromOUString(*this, rStr, eDestEncoding);
1178
2.02k
    return *this;
1179
2.02k
}
1180
1181
void SvStream::FlushBuffer()
1182
499M
{
1183
499M
    if (m_isDirty) // Does stream require a flush?
1184
3.77M
    {
1185
3.77M
        SeekPos(m_nBufFilePos);
1186
3.77M
        if (m_nCryptMask)
1187
0
            CryptAndWriteBuffer(m_pRWBuf.get(), m_nBufActualLen);
1188
3.77M
        else if (PutData(m_pRWBuf.get(), m_nBufActualLen) != m_nBufActualLen)
1189
2
            SetError(SVSTREAM_WRITE_ERROR);
1190
3.77M
        m_isDirty = false;
1191
3.77M
    }
1192
499M
}
1193
1194
std::size_t SvStream::ReadBytes( void* pData, std::size_t nCount )
1195
721M
{
1196
721M
    std::size_t nSaveCount = nCount;
1197
1198
721M
    if (!m_pRWBuf)
1199
464M
    {
1200
464M
        nCount = GetData( pData,nCount);
1201
464M
        if (m_nCryptMask)
1202
0
            EncryptBuffer(pData, nCount);
1203
464M
        m_nBufFilePos += nCount;
1204
464M
    }
1205
257M
    else
1206
257M
    {
1207
        // check if block is completely within buffer
1208
257M
        m_isIoRead = true;
1209
257M
        m_isIoWrite = false;
1210
257M
        if (nCount <= o3tl::make_unsigned(m_nBufActualLen - m_nBufActualPos))
1211
92.1M
        {
1212
            // => yes
1213
92.1M
            if (nCount != 0)
1214
92.0M
                memcpy(pData, m_pBufPos, nCount);
1215
92.1M
            m_nBufActualPos = m_nBufActualPos + static_cast<sal_uInt16>(nCount);
1216
92.1M
            m_pBufPos += nCount;
1217
92.1M
            m_nBufFree = m_nBufFree - static_cast<sal_uInt16>(nCount);
1218
92.1M
        }
1219
165M
        else
1220
165M
        {
1221
165M
            FlushBuffer();
1222
1223
            // Does data block fit into buffer?
1224
165M
            if (nCount > m_nBufSize)
1225
38.9M
            {
1226
                // => No! Thus read directly
1227
                // into target area without using the buffer
1228
1229
38.9M
                m_isIoRead = false;
1230
1231
38.9M
                SeekPos(m_nBufFilePos + m_nBufActualPos);
1232
38.9M
                m_nBufActualLen = 0;
1233
38.9M
                m_pBufPos     = m_pRWBuf.get();
1234
38.9M
                nCount = GetData( pData, nCount );
1235
38.9M
                if (m_nCryptMask)
1236
0
                    EncryptBuffer(pData, nCount);
1237
38.9M
                m_nBufFilePos += nCount;
1238
38.9M
                m_nBufFilePos += m_nBufActualPos;
1239
38.9M
                m_nBufActualPos = 0;
1240
38.9M
            }
1241
126M
            else
1242
126M
            {
1243
                // => Yes. Fill buffer first, then copy to target area
1244
1245
126M
                m_nBufFilePos += m_nBufActualPos;
1246
126M
                SeekPos(m_nBufFilePos);
1247
1248
                // TODO: Typecast before GetData, sal_uInt16 nCountTmp
1249
126M
                std::size_t nCountTmp = GetData( m_pRWBuf.get(), m_nBufSize );
1250
126M
                if (m_nCryptMask)
1251
0
                    EncryptBuffer(m_pRWBuf.get(), nCountTmp);
1252
126M
                m_nBufActualLen = static_cast<sal_uInt16>(nCountTmp);
1253
126M
                if( nCount > nCountTmp )
1254
118M
                {
1255
118M
                    nCount = nCountTmp;  // trim count back, EOF see below
1256
118M
                }
1257
126M
                memcpy( pData, m_pRWBuf.get(), nCount );
1258
126M
                m_nBufActualPos = static_cast<sal_uInt16>(nCount);
1259
126M
                m_pBufPos = m_pRWBuf.get() + nCount;
1260
126M
            }
1261
165M
        }
1262
257M
    }
1263
721M
    m_isEof = false;
1264
721M
    m_nBufFree = m_nBufActualLen - m_nBufActualPos;
1265
721M
    if (nCount != nSaveCount && m_nError != ERRCODE_IO_PENDING)
1266
189M
        m_isEof = true;
1267
721M
    if (nCount == nSaveCount && m_nError == ERRCODE_IO_PENDING)
1268
0
        m_nError = ERRCODE_NONE;
1269
721M
    return nCount;
1270
721M
}
1271
1272
std::size_t SvStream::WriteBytes( const void* pData, std::size_t nCount )
1273
82.9M
{
1274
82.9M
    if( !nCount )
1275
708k
        return 0;
1276
1277
82.2M
    if (!m_isWritable)
1278
0
    {
1279
0
        SetError( ERRCODE_IO_CANTWRITE );
1280
0
        return 0;
1281
0
    }
1282
1283
82.2M
    if (!m_pRWBuf)
1284
72.7M
    {
1285
72.7M
        if (m_nCryptMask)
1286
0
            nCount = CryptAndWriteBuffer( pData, nCount );
1287
72.7M
        else
1288
72.7M
            nCount = PutData( pData, nCount );
1289
72.7M
        m_nBufFilePos += nCount;
1290
72.7M
        return nCount;
1291
72.7M
    }
1292
1293
9.54M
    m_isIoRead = false;
1294
9.54M
    m_isIoWrite = true;
1295
9.54M
    if (nCount <= o3tl::make_unsigned(m_nBufSize - m_nBufActualPos))
1296
6.29M
    {
1297
6.29M
        memcpy( m_pBufPos, pData, nCount );
1298
6.29M
        m_nBufActualPos = m_nBufActualPos + static_cast<sal_uInt16>(nCount);
1299
        // Update length if buffer was updated
1300
6.29M
        if (m_nBufActualPos > m_nBufActualLen)
1301
6.29M
            m_nBufActualLen = m_nBufActualPos;
1302
1303
6.29M
        m_pBufPos += nCount;
1304
6.29M
        m_isDirty = true;
1305
6.29M
    }
1306
3.24M
    else
1307
3.24M
    {
1308
3.24M
        FlushBuffer();
1309
1310
        // Does data block fit into buffer?
1311
3.24M
        if (nCount > m_nBufSize)
1312
1.71M
        {
1313
1.71M
            m_isIoWrite = false;
1314
1.71M
            m_nBufFilePos += m_nBufActualPos;
1315
1.71M
            m_nBufActualLen = 0;
1316
1.71M
            m_nBufActualPos = 0;
1317
1.71M
            m_pBufPos     = m_pRWBuf.get();
1318
1.71M
            SeekPos(m_nBufFilePos);
1319
1.71M
            if (m_nCryptMask)
1320
0
                nCount = CryptAndWriteBuffer( pData, nCount );
1321
1.71M
            else
1322
1.71M
                nCount = PutData( pData, nCount );
1323
1.71M
            m_nBufFilePos += nCount;
1324
1.71M
        }
1325
1.52M
        else
1326
1.52M
        {
1327
            // Copy block to buffer
1328
1.52M
            memcpy( m_pRWBuf.get(), pData, nCount );
1329
1330
            // Mind the order!
1331
1.52M
            m_nBufFilePos += m_nBufActualPos;
1332
1.52M
            m_nBufActualPos = static_cast<sal_uInt16>(nCount);
1333
1.52M
            m_pBufPos = m_pRWBuf.get() + nCount;
1334
1.52M
            m_nBufActualLen = static_cast<sal_uInt16>(nCount);
1335
1.52M
            m_isDirty = true;
1336
1.52M
        }
1337
3.24M
    }
1338
9.54M
    m_nBufFree = m_nBufSize - m_nBufActualPos;
1339
9.54M
    return nCount;
1340
82.2M
}
1341
1342
sal_uInt64 SvStream::Seek(sal_uInt64 const nFilePos)
1343
390M
{
1344
390M
    m_isIoRead = m_isIoWrite = false;
1345
390M
    m_isEof = false;
1346
390M
    if (!m_pRWBuf)
1347
63.2M
    {
1348
63.2M
        m_nBufFilePos = SeekPos( nFilePos );
1349
63.2M
        DBG_ASSERT(Tell() == m_nBufFilePos,"Out Of Sync!");
1350
63.2M
        return m_nBufFilePos;
1351
63.2M
    }
1352
1353
    // Is seek position within buffer?
1354
327M
    if (nFilePos >= m_nBufFilePos && nFilePos <= (m_nBufFilePos + m_nBufActualLen))
1355
291M
    {
1356
291M
        m_nBufActualPos = static_cast<sal_uInt16>(nFilePos - m_nBufFilePos);
1357
291M
        m_pBufPos = m_pRWBuf.get() + m_nBufActualPos;
1358
        // Update m_nBufFree to avoid crash upon PutBack
1359
291M
        m_nBufFree = m_nBufActualLen - m_nBufActualPos;
1360
291M
    }
1361
35.8M
    else
1362
35.8M
    {
1363
35.8M
        FlushBuffer();
1364
35.8M
        m_nBufActualLen = 0;
1365
35.8M
        m_nBufActualPos = 0;
1366
35.8M
        m_pBufPos     = m_pRWBuf.get();
1367
35.8M
        m_nBufFilePos = SeekPos( nFilePos );
1368
35.8M
    }
1369
327M
    return m_nBufFilePos + m_nBufActualPos;
1370
390M
}
1371
1372
bool checkSeek(SvStream &rSt, sal_uInt64 nOffset)
1373
219M
{
1374
219M
    const sal_uInt64 nMaxSeek = rSt.TellEnd();
1375
219M
    return (nOffset <= nMaxSeek && rSt.Seek(nOffset) == nOffset);
1376
219M
}
1377
1378
namespace tools
1379
{
1380
bool isEmptyFileUrl(const OUString& rUrl)
1381
0
{
1382
0
    if (!comphelper::isFileUrl(rUrl))
1383
0
    {
1384
0
        return false;
1385
0
    }
1386
1387
0
    SvFileStream aStream(rUrl, StreamMode::READ);
1388
0
    if (!aStream.IsOpen())
1389
0
    {
1390
0
        return false;
1391
0
    }
1392
1393
0
    return aStream.remainingSize() == 0;
1394
0
}
1395
}
1396
1397
//STREAM_SEEK_TO_END in some of the Seek backends is special cased to be
1398
//efficient, in others e.g. SotStorageStream it's really horribly slow, and in
1399
//those this should be overridden
1400
sal_uInt64 SvStream::remainingSize()
1401
59.1M
{
1402
59.1M
    sal_uInt64 const nCurr = Tell();
1403
59.1M
    sal_uInt64 const nEnd = TellEnd();
1404
59.1M
    sal_uInt64 nMaxAvailable = nEnd > nCurr ? (nEnd-nCurr) : 0;
1405
59.1M
    return nMaxAvailable;
1406
59.1M
}
1407
1408
sal_uInt64 SvStream::TellEnd()
1409
12.3M
{
1410
12.3M
    FlushBuffer();
1411
12.3M
    sal_uInt64 const nCurr = Tell();
1412
12.3M
    sal_uInt64 const nEnd = Seek(STREAM_SEEK_TO_END);
1413
12.3M
    Seek(nCurr);
1414
12.3M
    return nEnd;
1415
12.3M
}
1416
1417
void SvStream::Flush()
1418
1.12M
{
1419
1.12M
    FlushBuffer();
1420
1.12M
    if (m_isWritable)
1421
883k
        FlushData();
1422
1.12M
}
1423
1424
void SvStream::RefreshBuffer()
1425
45.1k
{
1426
45.1k
    FlushBuffer();
1427
45.1k
    SeekPos(m_nBufFilePos);
1428
45.1k
    m_nBufActualLen = static_cast<sal_uInt16>(GetData( m_pRWBuf.get(), m_nBufSize ));
1429
45.1k
    if (m_nBufActualLen && m_nError == ERRCODE_IO_PENDING)
1430
0
        m_nError = ERRCODE_NONE;
1431
45.1k
    if (m_nCryptMask)
1432
0
        EncryptBuffer(m_pRWBuf.get(), static_cast<std::size_t>(m_nBufActualLen));
1433
45.1k
    m_isIoRead = m_isIoWrite = false;
1434
45.1k
}
1435
1436
0
#define CRYPT_BUFSIZE 1024
1437
1438
/// Encrypt and write
1439
std::size_t SvStream::CryptAndWriteBuffer( const void* pStart, std::size_t nLen)
1440
0
{
1441
0
    unsigned char  pTemp[CRYPT_BUFSIZE];
1442
0
    unsigned char const * pDataPtr = static_cast<unsigned char const *>(pStart);
1443
0
    std::size_t nCount = 0;
1444
0
    std::size_t nBufCount;
1445
0
    unsigned char nMask = m_nCryptMask;
1446
0
    do
1447
0
    {
1448
0
        if( nLen >= CRYPT_BUFSIZE )
1449
0
            nBufCount = CRYPT_BUFSIZE;
1450
0
        else
1451
0
            nBufCount = nLen;
1452
0
        nLen -= nBufCount;
1453
0
        memcpy( pTemp, pDataPtr, static_cast<sal_uInt16>(nBufCount) );
1454
        // ******** Encrypt ********
1455
0
        for (unsigned char & rn : pTemp)
1456
0
        {
1457
0
            unsigned char aCh = rn;
1458
0
            aCh ^= nMask;
1459
0
            swapNibbles(aCh);
1460
0
            rn = aCh;
1461
0
        }
1462
        // *************************
1463
0
        nCount += PutData( pTemp, nBufCount );
1464
0
        pDataPtr += nBufCount;
1465
0
    }
1466
0
    while ( nLen );
1467
0
    return nCount;
1468
0
}
1469
1470
void SvStream::EncryptBuffer(void* pStart, std::size_t nLen) const
1471
0
{
1472
0
    unsigned char* pTemp = static_cast<unsigned char*>(pStart);
1473
0
    unsigned char nMask = m_nCryptMask;
1474
1475
0
    for ( std::size_t n=0; n < nLen; n++, pTemp++ )
1476
0
    {
1477
0
        unsigned char aCh = *pTemp;
1478
0
        swapNibbles(aCh);
1479
0
        aCh ^= nMask;
1480
0
        *pTemp = aCh;
1481
0
    }
1482
0
}
1483
1484
static unsigned char implGetCryptMask(const char* pStr, sal_Int32 nLen, tools::Long nVersion)
1485
10.8k
{
1486
10.8k
    unsigned char nCryptMask = 0;
1487
1488
10.8k
    if (!nLen)
1489
10.8k
        return nCryptMask;
1490
1491
0
    if( nVersion <= SOFFICE_FILEFORMAT_31 )
1492
0
    {
1493
0
        while( nLen )
1494
0
        {
1495
0
            nCryptMask ^= *pStr;
1496
0
            pStr++;
1497
0
            nLen--;
1498
0
        }
1499
0
    }
1500
0
    else // BugFix #25888#
1501
0
    {
1502
0
        for( sal_Int32 i = 0; i < nLen; i++ ) {
1503
0
            nCryptMask ^= pStr[i];
1504
0
            if( nCryptMask & 0x80 ) {
1505
0
                nCryptMask <<= 1;
1506
0
                nCryptMask++;
1507
0
            }
1508
0
            else
1509
0
                nCryptMask <<= 1;
1510
0
        }
1511
0
    }
1512
1513
0
    if( !nCryptMask )
1514
0
        nCryptMask = 67;
1515
1516
0
    return nCryptMask;
1517
10.8k
}
1518
1519
void SvStream::SetCryptMaskKey(const OString& rCryptMaskKey)
1520
10.8k
{
1521
10.8k
    m_aCryptMaskKey = rCryptMaskKey;
1522
10.8k
    m_nCryptMask = implGetCryptMask(m_aCryptMaskKey.getStr(),
1523
10.8k
        m_aCryptMaskKey.getLength(), GetVersion());
1524
10.8k
}
1525
1526
bool SvStream::SetStreamSize(sal_uInt64 const nSize)
1527
271k
{
1528
#ifdef DBG_UTIL
1529
    sal_uInt64 nFPos = Tell();
1530
#endif
1531
271k
    sal_uInt16 nBuf = m_nBufSize;
1532
271k
    SetBufferSize( 0 );
1533
271k
    SetSize( nSize );
1534
271k
    if (nSize < m_nBufFilePos)
1535
0
    {
1536
0
        m_nBufFilePos = nSize;
1537
0
    }
1538
271k
    SetBufferSize( nBuf );
1539
#ifdef DBG_UTIL
1540
    DBG_ASSERT(Tell()==nFPos,"SetStreamSize failed");
1541
#endif
1542
271k
    return (m_nError == ERRCODE_NONE);
1543
271k
}
1544
1545
SvStream& endl( SvStream& rStr )
1546
0
{
1547
0
    LineEnd eDelim = rStr.GetLineDelimiter();
1548
0
    if ( eDelim == LINEEND_CR )
1549
0
        rStr.WriteChar('\r');
1550
0
    else if( eDelim == LINEEND_LF )
1551
0
        rStr.WriteChar('\n');
1552
0
    else
1553
0
        rStr.WriteChar('\r').WriteChar('\n');
1554
0
    return rStr;
1555
0
}
1556
1557
SvStream& endlu( SvStream& rStrm )
1558
0
{
1559
0
    switch ( rStrm.GetLineDelimiter() )
1560
0
    {
1561
0
        case LINEEND_CR :
1562
0
            rStrm.WriteUnicode('\r');
1563
0
        break;
1564
0
        case LINEEND_LF :
1565
0
            rStrm.WriteUnicode('\n');
1566
0
        break;
1567
0
        default:
1568
0
            rStrm.WriteUnicode('\r').WriteUnicode('\n');
1569
0
    }
1570
0
    return rStrm;
1571
0
}
1572
1573
SvStream& endlub( SvStream& rStrm )
1574
0
{
1575
0
    if (rStrm.GetStreamEncoding() == RTL_TEXTENCODING_UNICODE)
1576
0
        return endlu( rStrm );
1577
0
    else
1578
0
        return endl( rStrm );
1579
0
}
1580
1581
SvMemoryStream::SvMemoryStream( void* pBuffer, std::size_t bufSize,
1582
                                StreamMode eMode )
1583
4.08M
{
1584
4.08M
    if( eMode & StreamMode::WRITE )
1585
1.38M
        m_isWritable = true;
1586
2.69M
    else
1587
2.69M
        m_isWritable = false;
1588
4.08M
    nEndOfData  = bufSize;
1589
4.08M
    bOwnsData   = false;
1590
4.08M
    pBuf        = static_cast<sal_uInt8 *>(pBuffer);
1591
4.08M
    nResize     = 0;
1592
4.08M
    nSize       = bufSize;
1593
4.08M
    nPos        = 0;
1594
4.08M
    SetBufferSize( 0 );
1595
4.08M
}
1596
1597
SvMemoryStream::SvMemoryStream( std::size_t nInitSize, std::size_t nResizeOffset )
1598
1.13M
{
1599
1.13M
    m_isWritable = true;
1600
1.13M
    bOwnsData   = true;
1601
1.13M
    nEndOfData  = 0;
1602
1.13M
    nResize     = nResizeOffset;
1603
1.13M
    nPos        = 0;
1604
1.13M
    pBuf        = nullptr;
1605
1.13M
    if( nResize != 0 && nResize < 16 )
1606
0
        nResize = 16;
1607
1.13M
    if( nInitSize )
1608
1.13M
        AllocateMemory( nInitSize );
1609
1.13M
    nSize = nInitSize;
1610
1.13M
    SetBufferSize( 64 );
1611
1.13M
}
1612
1613
SvMemoryStream::~SvMemoryStream()
1614
5.22M
{
1615
5.22M
    if( pBuf )
1616
5.22M
    {
1617
5.22M
        if( bOwnsData )
1618
1.16M
            FreeMemory();
1619
4.05M
        else
1620
4.05M
            FlushBuffer();
1621
5.22M
    }
1622
5.22M
}
1623
1624
void SvMemoryStream::SetBuffer( void* pNewBuf, std::size_t nCount,
1625
                                 std::size_t nEOF )
1626
70.9k
{
1627
70.9k
    SetBufferSize( 0 ); // Init buffering in the base class
1628
70.9k
    Seek( 0 );
1629
70.9k
    if( bOwnsData && pNewBuf != pBuf )
1630
70.9k
        FreeMemory();
1631
1632
70.9k
    pBuf        = static_cast<sal_uInt8 *>(pNewBuf);
1633
70.9k
    nPos        = 0;
1634
70.9k
    nSize       = nCount;
1635
70.9k
    nResize     = 0;
1636
70.9k
    bOwnsData   = false;
1637
1638
70.9k
    if( nEOF > nCount )
1639
0
        nEOF = nCount;
1640
70.9k
    nEndOfData = nEOF;
1641
1642
70.9k
    ResetError();
1643
70.9k
}
1644
1645
std::size_t SvMemoryStream::GetData( void* pData, std::size_t nCount )
1646
466M
{
1647
466M
    std::size_t nMaxCount = nEndOfData-nPos;
1648
466M
    if( nCount > nMaxCount )
1649
82.8M
        nCount = nMaxCount;
1650
466M
    if (nCount != 0)
1651
384M
    {
1652
384M
        memcpy( pData, pBuf+nPos, nCount );
1653
384M
    }
1654
466M
    nPos += nCount;
1655
466M
    return nCount;
1656
466M
}
1657
1658
std::size_t SvMemoryStream::PutData( const void* pData, std::size_t nCount )
1659
76.2M
{
1660
76.2M
    if( GetError() )
1661
0
        return 0;
1662
1663
76.2M
    std::size_t nMaxCount = nSize-nPos;
1664
1665
    // check for overflow
1666
76.2M
    if( nCount > nMaxCount )
1667
89.9k
    {
1668
89.9k
        if( nResize == 0 )
1669
2
        {
1670
            // copy as much as possible
1671
2
            nCount = nMaxCount;
1672
2
            SetError( SVSTREAM_OUTOFMEMORY );
1673
2
        }
1674
89.9k
        else
1675
89.9k
        {
1676
#if BOOST_VERSION < 108600
1677
            const bool bSourceDataIsInsideBuffer = std::less_equal<sal_uInt8 const *>()(pBuf, static_cast<sal_uInt8 const *>(pData)) && std::less<sal_uInt8 const *>()(static_cast<sal_uInt8 const *>(pData), pBuf + nSize);
1678
#else
1679
89.9k
            const bool bSourceDataIsInsideBuffer = boost::pointer_in_range(
1680
89.9k
                static_cast<sal_uInt8 const *>(pData), pBuf, pBuf + nSize);
1681
89.9k
#endif
1682
89.9k
            std::ptrdiff_t const offset = bSourceDataIsInsideBuffer ? static_cast<const char*>(pData) - reinterpret_cast<const char*>(pBuf) : 0;
1683
89.9k
            tools::Long nNewResize;
1684
89.9k
            if( nSize && nSize > nResize )
1685
89.0k
                nNewResize = nSize;
1686
868
            else
1687
868
                nNewResize = nResize;
1688
1689
89.9k
            if( (nCount-nMaxCount) < nResize )
1690
40.5k
            {
1691
                // lacking memory is smaller than nResize,
1692
                // resize accordingly
1693
40.5k
                if( !ReAllocateMemory( nNewResize) )
1694
0
                {
1695
0
                    nCount = 0;
1696
0
                    SetError( SVSTREAM_WRITE_ERROR );
1697
0
                }
1698
40.5k
            }
1699
49.4k
            else
1700
49.4k
            {
1701
                // lacking memory is larger than nResize,
1702
                // resize by (nCount-nMaxCount) + resize offset
1703
49.4k
                if( !ReAllocateMemory( nCount-nMaxCount+nNewResize ) )
1704
0
                {
1705
0
                    nCount = 0;
1706
0
                    SetError( SVSTREAM_WRITE_ERROR );
1707
0
                }
1708
49.4k
            }
1709
89.9k
            if (bSourceDataIsInsideBuffer)
1710
0
                pData = pBuf + offset;
1711
89.9k
        }
1712
89.9k
    }
1713
76.2M
    assert(pBuf && "Possibly Reallocate failed");
1714
76.2M
    memcpy( pBuf+nPos, pData, nCount);
1715
1716
76.2M
    nPos += nCount;
1717
76.2M
    if( nPos > nEndOfData )
1718
3.89M
        nEndOfData = nPos;
1719
76.2M
    return nCount;
1720
76.2M
}
1721
1722
sal_uInt64 SvMemoryStream::SeekPos(sal_uInt64 const nNewPos)
1723
108M
{
1724
    // nEndOfData: First position in stream not allowed to read from
1725
    // nSize: Size of allocated buffer
1726
1727
    // check if a truncated STREAM_SEEK_TO_END was passed
1728
108M
    assert(nNewPos != SAL_MAX_UINT32);
1729
108M
    if( nNewPos < nEndOfData )
1730
43.0M
        nPos = nNewPos;
1731
65.1M
    else if( nNewPos == STREAM_SEEK_TO_END )
1732
50.0k
        nPos = nEndOfData;
1733
65.1M
    else
1734
65.1M
    {
1735
65.1M
        if( nNewPos >= nSize ) // Does buffer need extension?
1736
4.62M
        {
1737
4.62M
            if( nResize )  // Is extension possible?
1738
39.8k
            {
1739
39.8k
                tools::Long nDiff = static_cast<tools::Long>(nNewPos - nSize + 1);
1740
39.8k
                nDiff += static_cast<tools::Long>(nResize);
1741
39.8k
                ReAllocateMemory( nDiff );
1742
39.8k
                nPos = nNewPos;
1743
39.8k
                nEndOfData = nNewPos;
1744
39.8k
            }
1745
4.58M
            else  // Extension not possible, set pos to end of data
1746
4.58M
            {
1747
                // SetError( SVSTREAM_OUTOFMEMORY );
1748
4.58M
                nPos = nEndOfData;
1749
4.58M
            }
1750
4.62M
        }
1751
60.5M
        else  // Expand buffer size
1752
60.5M
        {
1753
60.5M
            nPos = nNewPos;
1754
60.5M
            nEndOfData = nNewPos;
1755
60.5M
        }
1756
65.1M
    }
1757
108M
    return nPos;
1758
108M
}
1759
1760
void SvMemoryStream::FlushData()
1761
9.86k
{
1762
9.86k
}
1763
1764
void SvMemoryStream::ResetError()
1765
340k
{
1766
340k
    SvStream::ClearError();
1767
340k
}
1768
1769
void SvMemoryStream::AllocateMemory( std::size_t nNewSize )
1770
1.13M
{
1771
1.13M
    pBuf = new sal_uInt8[nNewSize];
1772
1.13M
}
1773
1774
// (using Bozo algorithm)
1775
bool SvMemoryStream::ReAllocateMemory( tools::Long nDiff )
1776
656k
{
1777
656k
    if (!m_isWritable || !bOwnsData)
1778
0
        return false;
1779
1780
656k
    bool bRetVal    = false;
1781
656k
    tools::Long nTemp      = static_cast<tools::Long>(nSize);
1782
656k
    nTemp           += nDiff;
1783
656k
    std::size_t nNewSize  = static_cast<std::size_t>(nTemp);
1784
1785
656k
    if( nNewSize )
1786
656k
    {
1787
656k
        sal_uInt8* pNewBuf   = new sal_uInt8[nNewSize];
1788
1789
656k
        bRetVal = true; // Success!
1790
656k
        if( nNewSize < nSize )      // Are we shrinking?
1791
119k
        {
1792
119k
            memcpy( pNewBuf, pBuf, nNewSize );
1793
119k
            if( nPos > nNewSize )
1794
0
                nPos = 0;
1795
119k
            if( nEndOfData >= nNewSize )
1796
34.3k
                nEndOfData = nNewSize-1;
1797
119k
        }
1798
537k
        else
1799
537k
        {
1800
537k
            if (nSize != 0)
1801
537k
            {
1802
537k
                memcpy( pNewBuf, pBuf, nSize );
1803
537k
            }
1804
537k
            memset(pNewBuf + nSize, 0x00, nNewSize - nSize);
1805
537k
        }
1806
1807
656k
        FreeMemory();
1808
1809
656k
        pBuf  = pNewBuf;
1810
656k
        nSize = nNewSize;
1811
656k
    }
1812
0
    else
1813
0
    {
1814
0
        bRetVal = true;
1815
0
        FreeMemory();
1816
0
        pBuf = nullptr;
1817
0
        nSize = 0;
1818
0
        nEndOfData = 0;
1819
0
        nPos = 0;
1820
0
    }
1821
1822
656k
    return bRetVal;
1823
656k
}
1824
1825
void SvMemoryStream::FreeMemory()
1826
1.89M
{
1827
1.89M
    assert(bOwnsData);
1828
1.89M
    if (bOwnsData)
1829
1.89M
    {
1830
1.89M
        delete[] pBuf;
1831
1.89M
        pBuf = nullptr;
1832
1.89M
    }
1833
1.89M
}
1834
1835
void* SvMemoryStream::SwitchBuffer()
1836
5.33k
{
1837
5.33k
    FlushBuffer();
1838
5.33k
    if( !bOwnsData )
1839
0
        return nullptr;
1840
5.33k
    Seek( STREAM_SEEK_TO_BEGIN );
1841
1842
5.33k
    void* pRetVal = pBuf;
1843
5.33k
    pBuf          = nullptr;
1844
5.33k
    nEndOfData    = 0;
1845
5.33k
    nResize       = 64;
1846
5.33k
    nPos          = 0;
1847
1848
5.33k
    ResetError();
1849
1850
5.33k
    std::size_t nInitSize = 512;
1851
5.33k
    AllocateMemory(nInitSize);
1852
5.33k
    nSize = nInitSize;
1853
1854
5.33k
    SetBufferSize( 64 );
1855
5.33k
    return pRetVal;
1856
5.33k
}
1857
1858
void SvMemoryStream::SetSize(sal_uInt64 const nNewSize)
1859
515k
{
1860
515k
    if (!m_isWritable)
1861
0
    {
1862
0
        SetError(SVSTREAM_INVALID_HANDLE);
1863
0
        return;
1864
0
    }
1865
1866
515k
    tools::Long nDiff = static_cast<tools::Long>(nNewSize) - static_cast<tools::Long>(nSize);
1867
515k
    ReAllocateMemory( nDiff );
1868
515k
}
1869
1870
void SvMemoryStream::MakeReadOnly()
1871
0
{
1872
0
    FlushBuffer();
1873
0
    m_isWritable = false;
1874
0
    nResize     = 0;
1875
0
    SetBufferSize( 0 );
1876
0
}
1877
1878
// Create an OString of nLen bytes from rStream
1879
// coverity[ +taint_sanitize ]
1880
OString read_uInt8s_ToOString(SvStream& rStrm, std::size_t nLen)
1881
3.72M
{
1882
3.72M
    rtl_String *pStr = nullptr;
1883
3.72M
    if (nLen)
1884
468k
    {
1885
468k
        nLen = std::min<std::size_t>(nLen, SAL_MAX_INT32);
1886
        //limit allocation to size of file, but + 1 to set eof state
1887
468k
        nLen = std::min<sal_uInt64>(nLen, rStrm.remainingSize() + 1);
1888
        //alloc a (ref-count 1) rtl_String of the desired length.
1889
        //rtl_String's buffer is uninitialized, except for null termination
1890
468k
        pStr = rtl_string_alloc(sal::static_int_cast<sal_Int32>(nLen));
1891
468k
        SAL_WARN_IF(!pStr, "tools.stream", "allocation failed");
1892
468k
        if (pStr)
1893
468k
        {
1894
468k
            std::size_t nWasRead = rStrm.ReadBytes(pStr->buffer, nLen);
1895
468k
            if (nWasRead != nLen)
1896
16.9k
            {
1897
                //on (typically unlikely) short read set length to what we could
1898
                //read, and null terminate. Excess buffer capacity remains of
1899
                //course, could create a (true) replacement OString if it matters.
1900
16.9k
                pStr->length = sal::static_int_cast<sal_Int32>(nWasRead);
1901
16.9k
                pStr->buffer[pStr->length] = 0;
1902
16.9k
            }
1903
468k
        }
1904
468k
    }
1905
1906
    //take ownership of buffer and return, otherwise return empty string
1907
3.72M
    return pStr ? OString(pStr, SAL_NO_ACQUIRE) : OString();
1908
3.72M
}
1909
1910
// Create an OUString of nLen sal_Unicode code units from rStream
1911
// coverity[ +taint_sanitize ]
1912
OUString read_uInt16s_ToOUString(SvStream& rStrm, std::size_t nLen)
1913
876k
{
1914
876k
    rtl_uString *pStr = nullptr;
1915
876k
    if (nLen)
1916
243k
    {
1917
243k
        nLen = std::min<std::size_t>(nLen, SAL_MAX_INT32);
1918
        //limit allocation to size of file, but + 1 to set eof state
1919
243k
        nLen = o3tl::sanitizing_min<sal_uInt64>(nLen, (rStrm.remainingSize() + 2) / 2);
1920
        //alloc a (ref-count 1) rtl_uString of the desired length.
1921
        //rtl_String's buffer is uninitialized, except for null termination
1922
243k
        pStr = rtl_uString_alloc(sal::static_int_cast<sal_Int32>(nLen));
1923
243k
        SAL_WARN_IF(!pStr, "tools.stream", "allocation failed");
1924
243k
        if (pStr)
1925
243k
        {
1926
243k
            std::size_t nWasRead = rStrm.ReadBytes(pStr->buffer, nLen*2)/2;
1927
243k
            if (nWasRead != nLen)
1928
9.44k
            {
1929
                //on (typically unlikely) short read set length to what we could
1930
                //read, and null terminate. Excess buffer capacity remains of
1931
                //course, could create a (true) replacement OUString if it matters.
1932
9.44k
                pStr->length = sal::static_int_cast<sal_Int32>(nWasRead);
1933
9.44k
                pStr->buffer[pStr->length] = 0;
1934
9.44k
            }
1935
243k
            if (rStrm.IsEndianSwap())
1936
0
            {
1937
0
                for (sal_Int32 i = 0; i < pStr->length; ++i)
1938
0
                    pStr->buffer[i] = OSL_SWAPWORD(pStr->buffer[i]);
1939
0
            }
1940
243k
        }
1941
243k
    }
1942
1943
    // take ownership of buffer and return, otherwise return empty string
1944
    // coverity[tainted_data] - unhelpful untrusted loop bound
1945
876k
    return pStr ? OUString(pStr, SAL_NO_ACQUIRE) : OUString();
1946
876k
}
1947
1948
namespace
1949
{
1950
    template <typename T, typename O> T tmpl_convertLineEnd(const T &rIn, LineEnd eLineEnd)
1951
5.88M
    {
1952
        // Determine linebreaks and compute length
1953
5.88M
        bool            bConvert    = false;    // Needs conversion
1954
5.88M
        sal_Int32       nStrLen     = rIn.getLength();
1955
5.88M
        sal_Int32       nLineEndLen = (eLineEnd == LINEEND_CRLF) ? 2 : 1;
1956
5.88M
        sal_Int32       nLen        = 0;        // Target length
1957
5.88M
        sal_Int32       i           = 0;        // Source counter
1958
1959
155M
        while (i < nStrLen)
1960
149M
        {
1961
            // \r or \n causes linebreak
1962
149M
            if ( (rIn[i] == '\r') || (rIn[i] == '\n') )
1963
2.24M
            {
1964
2.24M
                nLen = nLen + nLineEndLen;
1965
1966
                // If set already, skip expensive test
1967
2.24M
                if ( !bConvert )
1968
1.82M
                {
1969
                    // Do we need to convert?
1970
1.82M
                    if ( ((eLineEnd != LINEEND_LF) && (rIn[i] == '\n')) ||
1971
1.82M
                         ((eLineEnd == LINEEND_CRLF) && (i+1) < nStrLen && (rIn[i+1] != '\n')) ||
1972
1.82M
                         ((eLineEnd == LINEEND_LF) &&
1973
1.82M
                          ((rIn[i] == '\r') || ((i+1) < nStrLen && rIn[i+1] == '\r'))) ||
1974
1.59M
                         ((eLineEnd == LINEEND_CR) &&
1975
0
                          ((rIn[i] == '\n') || ((i+1) < nStrLen && rIn[i+1] == '\n'))) )
1976
235k
                        bConvert = true;
1977
1.82M
                }
1978
1979
                // skip char if \r\n or \n\r
1980
2.24M
                if ( (i+1) < nStrLen && ((rIn[i+1] == '\r') || (rIn[i+1] == '\n')) &&
1981
1.13M
                     (rIn[i] != rIn[i+1]) )
1982
7.30k
                    ++i;
1983
2.24M
            }
1984
147M
            else
1985
147M
                ++nLen;
1986
149M
            ++i;
1987
149M
        }
1988
1989
5.88M
        if (!bConvert)
1990
5.64M
            return rIn;
1991
1992
        // convert linebreaks, insert string
1993
235k
        O aNewData(nLen);
1994
235k
        i = 0;
1995
10.7M
        while (i < nStrLen)
1996
10.5M
        {
1997
            // \r or \n causes linebreak
1998
10.5M
            if ( (rIn[i] == '\r') || (rIn[i] == '\n') )
1999
778k
            {
2000
778k
                if ( eLineEnd == LINEEND_CRLF )
2001
0
                {
2002
0
                    aNewData.append('\r');
2003
0
                    aNewData.append('\n');
2004
0
                }
2005
778k
                else
2006
778k
                {
2007
778k
                    if ( eLineEnd == LINEEND_CR )
2008
0
                        aNewData.append('\r');
2009
778k
                    else
2010
778k
                        aNewData.append('\n');
2011
778k
                }
2012
2013
778k
                if ( (i+1) < nStrLen && ((rIn[i+1] == '\r') || (rIn[i+1] == '\n')) &&
2014
419k
                     (rIn[i] != rIn[i+1]) )
2015
7.30k
                    ++i;
2016
778k
            }
2017
9.77M
            else
2018
9.77M
            {
2019
9.77M
                aNewData.append(rIn[i]);
2020
9.77M
            }
2021
2022
10.5M
            ++i;
2023
10.5M
        }
2024
2025
235k
        return aNewData.makeStringAndClear();
2026
5.88M
    }
Unexecuted instantiation: stream.cxx:rtl::OString (anonymous namespace)::tmpl_convertLineEnd<rtl::OString, rtl::OStringBuffer>(rtl::OString const&, LineEnd)
stream.cxx:rtl::OUString (anonymous namespace)::tmpl_convertLineEnd<rtl::OUString, rtl::OUStringBuffer>(rtl::OUString const&, LineEnd)
Line
Count
Source
1951
5.88M
    {
1952
        // Determine linebreaks and compute length
1953
5.88M
        bool            bConvert    = false;    // Needs conversion
1954
5.88M
        sal_Int32       nStrLen     = rIn.getLength();
1955
5.88M
        sal_Int32       nLineEndLen = (eLineEnd == LINEEND_CRLF) ? 2 : 1;
1956
5.88M
        sal_Int32       nLen        = 0;        // Target length
1957
5.88M
        sal_Int32       i           = 0;        // Source counter
1958
1959
155M
        while (i < nStrLen)
1960
149M
        {
1961
            // \r or \n causes linebreak
1962
149M
            if ( (rIn[i] == '\r') || (rIn[i] == '\n') )
1963
2.24M
            {
1964
2.24M
                nLen = nLen + nLineEndLen;
1965
1966
                // If set already, skip expensive test
1967
2.24M
                if ( !bConvert )
1968
1.82M
                {
1969
                    // Do we need to convert?
1970
1.82M
                    if ( ((eLineEnd != LINEEND_LF) && (rIn[i] == '\n')) ||
1971
1.82M
                         ((eLineEnd == LINEEND_CRLF) && (i+1) < nStrLen && (rIn[i+1] != '\n')) ||
1972
1.82M
                         ((eLineEnd == LINEEND_LF) &&
1973
1.82M
                          ((rIn[i] == '\r') || ((i+1) < nStrLen && rIn[i+1] == '\r'))) ||
1974
1.59M
                         ((eLineEnd == LINEEND_CR) &&
1975
0
                          ((rIn[i] == '\n') || ((i+1) < nStrLen && rIn[i+1] == '\n'))) )
1976
235k
                        bConvert = true;
1977
1.82M
                }
1978
1979
                // skip char if \r\n or \n\r
1980
2.24M
                if ( (i+1) < nStrLen && ((rIn[i+1] == '\r') || (rIn[i+1] == '\n')) &&
1981
1.13M
                     (rIn[i] != rIn[i+1]) )
1982
7.30k
                    ++i;
1983
2.24M
            }
1984
147M
            else
1985
147M
                ++nLen;
1986
149M
            ++i;
1987
149M
        }
1988
1989
5.88M
        if (!bConvert)
1990
5.64M
            return rIn;
1991
1992
        // convert linebreaks, insert string
1993
235k
        O aNewData(nLen);
1994
235k
        i = 0;
1995
10.7M
        while (i < nStrLen)
1996
10.5M
        {
1997
            // \r or \n causes linebreak
1998
10.5M
            if ( (rIn[i] == '\r') || (rIn[i] == '\n') )
1999
778k
            {
2000
778k
                if ( eLineEnd == LINEEND_CRLF )
2001
0
                {
2002
0
                    aNewData.append('\r');
2003
0
                    aNewData.append('\n');
2004
0
                }
2005
778k
                else
2006
778k
                {
2007
778k
                    if ( eLineEnd == LINEEND_CR )
2008
0
                        aNewData.append('\r');
2009
778k
                    else
2010
778k
                        aNewData.append('\n');
2011
778k
                }
2012
2013
778k
                if ( (i+1) < nStrLen && ((rIn[i+1] == '\r') || (rIn[i+1] == '\n')) &&
2014
419k
                     (rIn[i] != rIn[i+1]) )
2015
7.30k
                    ++i;
2016
778k
            }
2017
9.77M
            else
2018
9.77M
            {
2019
9.77M
                aNewData.append(rIn[i]);
2020
9.77M
            }
2021
2022
10.5M
            ++i;
2023
10.5M
        }
2024
2025
235k
        return aNewData.makeStringAndClear();
2026
5.88M
    }
2027
}
2028
2029
OString convertLineEnd(const OString &rIn, LineEnd eLineEnd)
2030
0
{
2031
0
    return tmpl_convertLineEnd<OString, OStringBuffer>(rIn, eLineEnd);
2032
0
}
2033
2034
OUString convertLineEnd(const OUString &rIn, LineEnd eLineEnd)
2035
5.88M
{
2036
5.88M
    return tmpl_convertLineEnd<OUString, OUStringBuffer>(rIn, eLineEnd);
2037
5.88M
}
2038
2039
std::size_t write_uInt32_lenPrefixed_uInt16s_FromOUString(SvStream& rStrm,
2040
                                                std::u16string_view rStr)
2041
675
{
2042
675
    std::size_t nWritten = 0;
2043
675
    sal_uInt32 nUnits = std::min<std::size_t>(rStr.size(), std::numeric_limits<sal_uInt32>::max());
2044
675
    SAL_WARN_IF(static_cast<std::size_t>(nUnits) != static_cast<std::size_t>(rStr.size()),
2045
675
        "tools.stream",
2046
675
        "string too long for prefix count to fit in output type");
2047
675
    rStrm.WriteUInt32(nUnits);
2048
675
    if (rStrm.good())
2049
675
    {
2050
675
        nWritten += sizeof(sal_uInt32);
2051
675
        nWritten += write_uInt16s_FromOUString(rStrm, rStr, nUnits);
2052
675
    }
2053
675
    return nWritten;
2054
675
}
2055
2056
std::size_t write_uInt16_lenPrefixed_uInt16s_FromOUString(SvStream& rStrm,
2057
                                                std::u16string_view rStr)
2058
675
{
2059
675
    std::size_t nWritten = 0;
2060
675
    sal_uInt16 nUnits = std::min<std::size_t>(rStr.size(), std::numeric_limits<sal_uInt16>::max());
2061
675
    SAL_WARN_IF(nUnits != rStr.size(),
2062
675
        "tools.stream",
2063
675
        "string too long for prefix count to fit in output type");
2064
675
    rStrm.WriteUInt16(nUnits);
2065
675
    if (rStrm.good())
2066
675
    {
2067
675
        nWritten += sizeof(nUnits);
2068
675
        nWritten += write_uInt16s_FromOUString(rStrm, rStr, nUnits);
2069
675
    }
2070
675
    return nWritten;
2071
675
}
2072
2073
std::size_t write_uInt16_lenPrefixed_uInt8s_FromOString(SvStream& rStrm,
2074
                                              std::string_view rStr)
2075
6.27k
{
2076
6.27k
    std::size_t nWritten = 0;
2077
6.27k
    sal_uInt16 nUnits = std::min<std::size_t>(rStr.size(), std::numeric_limits<sal_uInt16>::max());
2078
6.27k
    SAL_WARN_IF(static_cast<std::size_t>(nUnits) != static_cast<std::size_t>(rStr.size()),
2079
6.27k
        "tools.stream",
2080
6.27k
        "string too long for sal_uInt16 count to fit in output type");
2081
6.27k
    rStrm.WriteUInt16( nUnits );
2082
6.27k
    if (rStrm.good())
2083
6.27k
    {
2084
6.27k
        nWritten += sizeof(sal_uInt16);
2085
6.27k
        nWritten += rStrm.WriteBytes(rStr.data(), nUnits);
2086
6.27k
    }
2087
6.27k
    return nWritten;
2088
6.27k
}
2089
2090
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */