Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/io/source/stm/odata.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
#include <string.h>
21
#include <unordered_map>
22
#include <vector>
23
24
#include <cppuhelper/weak.hxx>
25
#include <cppuhelper/implbase.hxx>
26
#include <cppuhelper/supportsservice.hxx>
27
#include <osl/endian.h>
28
29
#include <com/sun/star/io/NotConnectedException.hpp>
30
#include <com/sun/star/io/XObjectInputStream.hpp>
31
#include <com/sun/star/io/XObjectOutputStream.hpp>
32
#include <com/sun/star/io/XActiveDataSource.hpp>
33
#include <com/sun/star/io/XActiveDataSink.hpp>
34
#include <com/sun/star/io/XMarkableStream.hpp>
35
#include <com/sun/star/io/XConnectable.hpp>
36
#include <com/sun/star/io/UnexpectedEOFException.hpp>
37
#include <com/sun/star/io/WrongFormatException.hpp>
38
#include <com/sun/star/lang/XServiceInfo.hpp>
39
#include <com/sun/star/uno/XComponentContext.hpp>
40
41
using namespace ::cppu;
42
using namespace ::com::sun::star::io;
43
using namespace ::com::sun::star::uno;
44
using namespace ::com::sun::star::lang;
45
46
namespace io_stm {
47
48
namespace {
49
50
class ODataInputStream :
51
    public WeakImplHelper <
52
                              XDataInputStream,
53
                              XActiveDataSink,
54
                              XConnectable,
55
                              XServiceInfo
56
                           >
57
{
58
public:
59
    ODataInputStream( )
60
0
        : m_bValidStream( false )
61
0
        {
62
0
        }
63
64
public: // XInputStream
65
    virtual sal_Int32 SAL_CALL readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) override;
66
    virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) override;
67
    virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) override;
68
    virtual sal_Int32 SAL_CALL available() override;
69
    virtual void SAL_CALL closeInput() override;
70
71
public: // XDataInputStream
72
    virtual sal_Int8 SAL_CALL readBoolean() override;
73
    virtual sal_Int8 SAL_CALL readByte() override;
74
    virtual sal_Unicode SAL_CALL readChar() override;
75
    virtual sal_Int16 SAL_CALL readShort() override;
76
    virtual sal_Int32 SAL_CALL readLong() override;
77
    virtual sal_Int64 SAL_CALL readHyper() override;
78
    virtual float SAL_CALL readFloat() override;
79
    virtual double SAL_CALL readDouble() override;
80
    virtual OUString SAL_CALL readUTF() override;
81
82
83
public: // XActiveDataSink
84
    virtual void SAL_CALL setInputStream(const Reference< XInputStream > & aStream) override;
85
    virtual Reference< XInputStream > SAL_CALL getInputStream() override;
86
87
public: // XConnectable
88
    virtual void SAL_CALL setPredecessor(const Reference < XConnectable >& aPredecessor) override;
89
    virtual Reference < XConnectable > SAL_CALL getPredecessor() override;
90
    virtual void SAL_CALL setSuccessor(const Reference < XConnectable >& aSuccessor) override;
91
    virtual Reference < XConnectable > SAL_CALL getSuccessor() override ;
92
93
94
public: // XServiceInfo
95
    OUString                     SAL_CALL getImplementationName() override;
96
    Sequence< OUString >         SAL_CALL getSupportedServiceNames() override;
97
    sal_Bool                        SAL_CALL supportsService(const OUString& ServiceName) override;
98
99
protected:
100
101
    Reference < XConnectable >  m_pred;
102
    Reference < XConnectable >  m_succ;
103
    Reference < XInputStream >  m_input;
104
    bool m_bValidStream;
105
};
106
107
}
108
109
// XInputStream
110
sal_Int32 ODataInputStream::readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
111
0
{
112
0
     if( !m_bValidStream )
113
0
     {
114
0
         throw NotConnectedException( );
115
0
     }
116
0
     sal_Int32 nRead = m_input->readBytes( aData , nBytesToRead );
117
0
     return nRead;
118
0
}
119
120
sal_Int32 ODataInputStream::readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
121
0
{
122
0
     if( !m_bValidStream )
123
0
         throw NotConnectedException( );
124
0
     sal_Int32 nRead = m_input->readSomeBytes( aData , nMaxBytesToRead );
125
0
     return nRead;
126
0
}
127
void ODataInputStream::skipBytes(sal_Int32 nBytesToSkip)
128
0
{
129
0
     if( !m_bValidStream )
130
0
         throw NotConnectedException( );
131
0
     m_input->skipBytes( nBytesToSkip );
132
0
}
133
134
135
sal_Int32 ODataInputStream::available()
136
0
{
137
0
     if( !m_bValidStream )
138
0
         throw NotConnectedException( );
139
0
     sal_Int32 nAvail = m_input->available( );
140
0
     return nAvail;
141
0
}
142
143
void ODataInputStream::closeInput()
144
0
{
145
0
     if( !m_bValidStream )
146
0
         throw NotConnectedException( );
147
0
     m_input->closeInput( );
148
0
     setInputStream( Reference< XInputStream > () );
149
0
     setPredecessor( Reference < XConnectable >() );
150
0
     setSuccessor( Reference < XConnectable >() );
151
0
     m_bValidStream = false;
152
0
}
153
154
155
//== XDataInputStream ===========================================
156
157
// XDataInputStream
158
sal_Int8 ODataInputStream::readBoolean()
159
0
{
160
0
    return readByte();
161
0
}
162
163
sal_Int8 ODataInputStream::readByte()
164
0
{
165
0
    Sequence<sal_Int8> aTmp(1);
166
0
    if( 1 != readBytes( aTmp, 1 ) )
167
0
    {
168
0
        throw UnexpectedEOFException();
169
0
    }
170
0
    return aTmp[0];
171
0
}
172
173
sal_Unicode ODataInputStream::readChar()
174
0
{
175
0
    Sequence<sal_Int8> aTmp(2);
176
0
    if( 2 != readBytes( aTmp, 2 ) )
177
0
    {
178
0
        throw UnexpectedEOFException();
179
0
    }
180
181
0
    const sal_uInt8 * pBytes = reinterpret_cast<const sal_uInt8 *>(aTmp.getConstArray());
182
0
    return (static_cast<sal_Unicode>(pBytes[0]) << 8) + pBytes[1];
183
0
}
184
185
sal_Int16 ODataInputStream::readShort()
186
0
{
187
0
    Sequence<sal_Int8> aTmp(2);
188
0
    if( 2 != readBytes( aTmp, 2 ) )
189
0
    {
190
0
        throw UnexpectedEOFException();
191
0
    }
192
193
0
    const sal_uInt8 * pBytes = reinterpret_cast<const sal_uInt8 *>(aTmp.getConstArray());
194
0
    return (static_cast<sal_Int16>(pBytes[0]) << 8) + pBytes[1];
195
0
}
196
197
198
sal_Int32 ODataInputStream::readLong()
199
0
{
200
0
    Sequence<sal_Int8> aTmp(4);
201
0
    if( 4 != readBytes( aTmp, 4 ) )
202
0
    {
203
0
        throw UnexpectedEOFException( );
204
0
    }
205
206
0
    const sal_uInt8 * pBytes = reinterpret_cast<const sal_uInt8 *>(aTmp.getConstArray());
207
0
    return (static_cast<sal_Int32>(pBytes[0]) << 24) + (static_cast<sal_Int32>(pBytes[1]) << 16) + (static_cast<sal_Int32>(pBytes[2]) << 8) + pBytes[3];
208
0
}
209
210
211
sal_Int64 ODataInputStream::readHyper()
212
0
{
213
0
    Sequence<sal_Int8> aTmp(8);
214
0
    if( 8 != readBytes( aTmp, 8 ) )
215
0
    {
216
0
        throw UnexpectedEOFException( );
217
0
    }
218
219
0
    const sal_uInt8 * pBytes = reinterpret_cast<const sal_uInt8 *>(aTmp.getConstArray());
220
0
    return
221
0
        (static_cast<sal_Int64>(pBytes[0]) << 56) +
222
0
        (static_cast<sal_Int64>(pBytes[1]) << 48) +
223
0
        (static_cast<sal_Int64>(pBytes[2]) << 40) +
224
0
        (static_cast<sal_Int64>(pBytes[3]) << 32) +
225
0
        (static_cast<sal_Int64>(pBytes[4]) << 24) +
226
0
        (static_cast<sal_Int64>(pBytes[5]) << 16) +
227
0
        (static_cast<sal_Int64>(pBytes[6]) << 8) +
228
0
        pBytes[7];
229
0
}
230
231
float ODataInputStream::readFloat()
232
0
{
233
0
    union { float f; sal_uInt32 n; } a;
234
0
    a.n = readLong();
235
0
    return a.f;
236
0
}
237
238
double ODataInputStream::readDouble()
239
0
{
240
0
    union { double d; struct { sal_uInt32 n1; sal_uInt32 n2; } ad; } a;
241
0
#if defined OSL_LITENDIAN
242
0
    a.ad.n2 = readLong();
243
0
    a.ad.n1 = readLong();
244
#else
245
    a.ad.n1 = readLong();
246
    a.ad.n2 = readLong();
247
#endif
248
0
    return a.d;
249
0
}
250
251
OUString ODataInputStream::readUTF()
252
0
{
253
0
    sal_uInt16              nShortLen = static_cast<sal_uInt16>(readShort());
254
0
    sal_Int32               nUTFLen;
255
256
0
    if( (sal_uInt16(0xffff)) == nShortLen )
257
0
    {
258
        // is interpreted as a sign, that string is longer than 64k
259
        // incompatible to older XDataInputStream-routines, when strings are exactly 64k
260
0
        nUTFLen = readLong();
261
0
    }
262
0
    else
263
0
    {
264
0
        nUTFLen = static_cast<sal_Int32>(nShortLen);
265
0
    }
266
267
0
    Sequence<sal_Unicode>   aBuffer( nUTFLen );
268
0
    sal_Unicode *           pStr = aBuffer.getArray();
269
270
0
    sal_Int32 nCount = 0;
271
0
    sal_Int32 nStrLen = 0;
272
0
    while( nCount < nUTFLen )
273
0
    {
274
0
        sal_uInt8 c = static_cast<sal_uInt8>(readByte());
275
0
        sal_uInt8 char2, char3;
276
0
        switch( c >> 4 )
277
0
        {
278
0
            case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
279
                // 0xxxxxxx
280
0
                nCount++;
281
0
                pStr[nStrLen++] = c;
282
0
                break;
283
284
0
            case 12: case 13:
285
                // 110x xxxx   10xx xxxx
286
0
                nCount += 2;
287
0
                if( nCount > nUTFLen )
288
0
                {
289
0
                    throw WrongFormatException( );
290
0
                }
291
292
0
                char2 = static_cast<sal_uInt8>(readByte());
293
0
                if( (char2 & 0xC0) != 0x80 )
294
0
                {
295
0
                    throw WrongFormatException( );
296
0
                }
297
298
0
                pStr[nStrLen++] = (sal_Unicode(c & 0x1F) << 6) | (char2 & 0x3F);
299
0
                break;
300
301
0
            case 14:
302
            // 1110 xxxx  10xx xxxx  10xx xxxx
303
0
                nCount += 3;
304
0
                if( nCount > nUTFLen )
305
0
                {
306
0
                    throw WrongFormatException( );
307
0
                }
308
309
0
                char2 = static_cast<sal_uInt8>(readByte());
310
0
                char3 = static_cast<sal_uInt8>(readByte());
311
312
0
                if( ((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80) ) {
313
0
                    throw WrongFormatException( );
314
0
                }
315
0
                pStr[nStrLen++] = (sal_Unicode(c & 0x0F) << 12) |
316
0
                                (sal_Unicode(char2 & 0x3F) << 6) |
317
0
                                (char3 & 0x3F);
318
0
                break;
319
320
0
            default:
321
                // 10xx xxxx,  1111 xxxx
322
0
                throw WrongFormatException();
323
                //throw new UTFDataFormatException();
324
0
        }
325
0
    }
326
0
    return OUString( pStr, nStrLen );
327
0
}
328
329
330
// XActiveDataSource
331
void ODataInputStream::setInputStream(const Reference< XInputStream > & aStream)
332
0
{
333
334
0
    if( m_input != aStream ) {
335
0
        m_input = aStream;
336
337
0
        Reference < XConnectable > pred( m_input , UNO_QUERY );
338
0
        setPredecessor( pred );
339
0
    }
340
341
0
    m_bValidStream = m_input.is();
342
0
}
343
344
Reference< XInputStream > ODataInputStream::getInputStream()
345
0
{
346
0
    return m_input;
347
0
}
348
349
350
// XDataSink
351
void ODataInputStream::setSuccessor( const Reference < XConnectable > &r )
352
0
{
353
     /// if the references match, nothing needs to be done
354
0
     if( m_succ != r ) {
355
         /// store the reference for later use
356
0
         m_succ = r;
357
358
0
         if( m_succ.is() ) {
359
              /// set this instance as the sink !
360
0
              m_succ->setPredecessor( Reference< XConnectable > (
361
0
                  static_cast< XConnectable * >(this) ) );
362
0
         }
363
0
     }
364
0
}
365
366
Reference < XConnectable > ODataInputStream::getSuccessor()
367
0
{
368
0
    return m_succ;
369
0
}
370
371
372
// XDataSource
373
void ODataInputStream::setPredecessor( const Reference < XConnectable > &r )
374
0
{
375
0
    if( r != m_pred ) {
376
0
        m_pred = r;
377
0
        if( m_pred.is() ) {
378
0
            m_pred->setSuccessor( Reference< XConnectable > (
379
0
                static_cast< XConnectable * >(this) ) );
380
0
        }
381
0
    }
382
0
}
383
Reference < XConnectable > ODataInputStream::getPredecessor()
384
0
{
385
0
    return m_pred;
386
0
}
387
388
// XServiceInfo
389
OUString ODataInputStream::getImplementationName()
390
0
{
391
0
    return u"com.sun.star.comp.io.stm.DataInputStream"_ustr;
392
0
}
393
394
// XServiceInfo
395
sal_Bool ODataInputStream::supportsService(const OUString& ServiceName)
396
0
{
397
0
    return cppu::supportsService(this, ServiceName);
398
0
}
399
400
// XServiceInfo
401
Sequence< OUString > ODataInputStream::getSupportedServiceNames()
402
0
{
403
0
    return { u"com.sun.star.io.DataInputStream"_ustr };
404
0
}
405
406
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
407
io_ODataInputStream_get_implementation(
408
    css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
409
0
{
410
0
    return cppu::acquire(new ODataInputStream());
411
0
}
412
413
namespace {
414
415
class ODataOutputStream :
416
    public WeakImplHelper <
417
             XDataOutputStream,
418
             XActiveDataSource,
419
             XConnectable,
420
              XServiceInfo >
421
{
422
public:
423
    ODataOutputStream()
424
0
        : m_bValidStream( false )
425
0
        {
426
0
        }
427
428
public: // XOutputStream
429
    virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData) override;
430
    virtual void SAL_CALL flush() override;
431
    virtual void SAL_CALL closeOutput() override;
432
433
public: // XDataOutputStream
434
    virtual void SAL_CALL writeBoolean(sal_Bool Value) override;
435
    virtual void SAL_CALL writeByte(sal_Int8 Value) override;
436
    virtual void SAL_CALL writeChar(sal_Unicode Value) override;
437
    virtual void SAL_CALL writeShort(sal_Int16 Value) override;
438
    virtual void SAL_CALL writeLong(sal_Int32 Value) override;
439
    virtual void SAL_CALL writeHyper(sal_Int64 Value) override;
440
    virtual void SAL_CALL writeFloat(float Value) override;
441
    virtual void SAL_CALL writeDouble(double Value) override;
442
    virtual void SAL_CALL writeUTF(const OUString& Value) override;
443
444
public: // XActiveDataSource
445
    virtual void SAL_CALL setOutputStream(const Reference< XOutputStream > & aStream) override;
446
    virtual Reference < XOutputStream > SAL_CALL getOutputStream() override;
447
448
public: // XConnectable
449
    virtual void SAL_CALL setPredecessor(const Reference < XConnectable >& aPredecessor) override;
450
    virtual Reference < XConnectable > SAL_CALL getPredecessor() override;
451
    virtual void SAL_CALL setSuccessor(const Reference < XConnectable >& aSuccessor) override;
452
    virtual Reference < XConnectable > SAL_CALL getSuccessor() override;
453
454
public: // XServiceInfo
455
    OUString                     SAL_CALL getImplementationName() override;
456
    Sequence< OUString >         SAL_CALL getSupportedServiceNames() override;
457
    sal_Bool                     SAL_CALL supportsService(const OUString& ServiceName) override;
458
459
protected:
460
    Reference < XConnectable >  m_succ;
461
    Reference < XConnectable >  m_pred;
462
    Reference<  XOutputStream > m_output;
463
    bool m_bValidStream;
464
};
465
466
}
467
468
// XOutputStream
469
void ODataOutputStream::writeBytes(const Sequence< sal_Int8 >& aData)
470
0
{
471
0
    if( !m_bValidStream )
472
0
        throw NotConnectedException( );
473
0
    m_output->writeBytes( aData );
474
0
}
475
476
void ODataOutputStream::flush()
477
0
{
478
0
    if( !m_bValidStream )
479
0
        throw NotConnectedException();
480
0
    m_output->flush();
481
0
}
482
483
484
void ODataOutputStream::closeOutput()
485
0
{
486
0
    if( !m_bValidStream )
487
0
        throw NotConnectedException();
488
0
    m_output->closeOutput();
489
0
    setOutputStream( Reference< XOutputStream > () );
490
0
    setPredecessor( Reference < XConnectable >() );
491
0
    setSuccessor( Reference < XConnectable >() );
492
0
}
493
494
// XDataOutputStream
495
void ODataOutputStream::writeBoolean(sal_Bool Value)
496
0
{
497
0
    if( Value )
498
0
    {
499
0
        writeByte( 1 );
500
0
    }
501
0
    else
502
0
    {
503
0
        writeByte( 0 );
504
0
    }
505
0
}
506
507
508
void ODataOutputStream::writeByte(sal_Int8 Value)
509
0
{
510
0
    writeBytes( { Value } );
511
0
}
512
513
void ODataOutputStream::writeChar(sal_Unicode Value)
514
0
{
515
0
    writeBytes( { sal_Int8(Value >> 8),
516
0
                  sal_Int8(Value) } );
517
0
}
518
519
520
void ODataOutputStream::writeShort(sal_Int16 Value)
521
0
{
522
0
    writeBytes( { sal_Int8(Value >> 8),
523
0
                  sal_Int8(Value) } );
524
0
}
525
526
void ODataOutputStream::writeLong(sal_Int32 Value)
527
0
{
528
0
    writeBytes( { sal_Int8(Value >> 24),
529
0
                  sal_Int8(Value >> 16),
530
0
                  sal_Int8(Value >> 8),
531
0
                  sal_Int8(Value) } );
532
0
}
533
534
void ODataOutputStream::writeHyper(sal_Int64 Value)
535
0
{
536
0
    writeBytes( { sal_Int8(Value >> 56),
537
0
                  sal_Int8(Value >> 48),
538
0
                  sal_Int8(Value >> 40),
539
0
                  sal_Int8(Value >> 32),
540
0
                  sal_Int8(Value >> 24),
541
0
                  sal_Int8(Value >> 16),
542
0
                  sal_Int8(Value >> 8),
543
0
                  sal_Int8(Value) } );
544
0
}
545
546
547
void ODataOutputStream::writeFloat(float Value)
548
0
{
549
0
    union { float f; sal_uInt32 n; } a;
550
0
    a.f = Value;
551
0
    writeLong( a.n );
552
0
}
553
554
void ODataOutputStream::writeDouble(double Value)
555
0
{
556
0
    union { double d; struct { sal_uInt32 n1; sal_uInt32 n2; } ad; } a;
557
0
    a.d = Value;
558
0
#if defined OSL_LITENDIAN
559
0
    writeLong( a.ad.n2 );
560
0
    writeLong( a.ad.n1 );
561
#else
562
    writeLong( a.ad.n1 );
563
    writeLong( a.ad.n2 );
564
#endif
565
0
}
566
567
void ODataOutputStream::writeUTF(const OUString& Value)
568
0
{
569
0
    sal_Int32 nStrLen = Value.getLength();
570
0
    const sal_Unicode * pStr = Value.getStr();
571
0
    sal_Int32 nUTFLen = 0;
572
0
    sal_Int32 i;
573
574
0
    for( i = 0 ; i < nStrLen ; i++ )
575
0
    {
576
0
        sal_uInt16 c = pStr[i];
577
0
        if( (c >= 0x0001) && (c <= 0x007F) )
578
0
        {
579
0
            nUTFLen++;
580
0
        }
581
0
        else if( c > 0x07FF )
582
0
        {
583
0
            nUTFLen += 3;
584
0
        }
585
0
        else
586
0
        {
587
0
            nUTFLen += 2;
588
0
        }
589
0
    }
590
591
592
    // compatibility mode for older implementations, where it was not possible
593
    // to write blocks bigger than 64 k. Note that there is a tradeoff. Blocks,
594
    // that are exactly 64k long can not be read by older routines when written
595
    // with these routines and the other way round !!!!!
596
0
    if( nUTFLen >= 0xFFFF ) {
597
0
        writeShort( sal_Int16(-1) );
598
0
        writeLong( nUTFLen );
599
0
    }
600
0
    else {
601
0
        writeShort( static_cast<sal_uInt16>(nUTFLen) );
602
0
    }
603
0
    for( i = 0 ; i < nStrLen ; i++ )
604
0
    {
605
0
        sal_uInt16 c = pStr[i];
606
0
        if( (c >= 0x0001) && (c <= 0x007F) )
607
0
        {
608
0
            writeByte(sal_Int8(c));
609
0
        }
610
0
        else if( c > 0x07FF )
611
0
        {
612
0
            writeByte(sal_Int8(0xE0 | ((c >> 12) & 0x0F)));
613
0
            writeByte(sal_Int8(0x80 | ((c >>  6) & 0x3F)));
614
0
            writeByte(sal_Int8(0x80 | ((c >>  0) & 0x3F)));
615
0
        }
616
0
        else
617
0
        {
618
0
            writeByte(sal_Int8(0xC0 | ((c >>  6) & 0x1F)));
619
0
            writeByte(sal_Int8(0x80 | ((c >>  0) & 0x3F)));
620
0
        }
621
0
    }
622
0
}
623
624
// XActiveDataSource
625
void ODataOutputStream::setOutputStream(const Reference< XOutputStream > & aStream)
626
0
{
627
0
    if( m_output != aStream ) {
628
0
        m_output = aStream;
629
0
        m_bValidStream = m_output.is();
630
631
0
        Reference < XConnectable > succ( m_output , UNO_QUERY );
632
0
        setSuccessor( succ );
633
0
    }
634
0
}
635
636
Reference< XOutputStream > ODataOutputStream::getOutputStream()
637
0
{
638
0
    return m_output;
639
0
}
640
641
642
// XDataSink
643
void ODataOutputStream::setSuccessor( const Reference < XConnectable > &r )
644
0
{
645
     /// if the references match, nothing needs to be done
646
0
     if( m_succ != r )
647
0
     {
648
         /// store the reference for later use
649
0
         m_succ = r;
650
651
0
         if( m_succ.is() )
652
0
         {
653
              /// set this instance as the sink !
654
0
              m_succ->setPredecessor( Reference < XConnectable > (
655
0
                  static_cast< XConnectable * >(this) ));
656
0
         }
657
0
     }
658
0
}
659
Reference < XConnectable > ODataOutputStream::getSuccessor()
660
0
{
661
0
    return m_succ;
662
0
}
663
664
665
// XDataSource
666
void ODataOutputStream::setPredecessor( const Reference < XConnectable > &r )
667
0
{
668
0
    if( r != m_pred ) {
669
0
        m_pred = r;
670
0
        if( m_pred.is() ) {
671
0
            m_pred->setSuccessor( Reference< XConnectable > (
672
0
                static_cast< XConnectable * >(this) ));
673
0
        }
674
0
    }
675
0
}
676
Reference < XConnectable > ODataOutputStream::getPredecessor()
677
0
{
678
0
    return m_pred;
679
0
}
680
681
682
// XServiceInfo
683
OUString ODataOutputStream::getImplementationName()
684
0
{
685
0
    return u"com.sun.star.comp.io.stm.DataOutputStream"_ustr;
686
0
}
687
688
// XServiceInfo
689
sal_Bool ODataOutputStream::supportsService(const OUString& ServiceName)
690
0
{
691
0
    return cppu::supportsService(this, ServiceName);
692
0
}
693
694
// XServiceInfo
695
Sequence< OUString > ODataOutputStream::getSupportedServiceNames()
696
0
{
697
0
    return { u"com.sun.star.io.DataOutputStream"_ustr };
698
0
}
699
700
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
701
io_ODataOutputStream_get_implementation(
702
    css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
703
0
{
704
0
    return cppu::acquire(new ODataOutputStream());
705
0
}
706
707
namespace {
708
709
struct equalObjectContainer_Impl
710
{
711
    bool operator()(const Reference< XInterface > & s1,
712
                         const Reference< XInterface > & s2) const
713
0
      {
714
0
        return s1 == s2;
715
0
    }
716
};
717
718
719
struct hashObjectContainer_Impl
720
{
721
    size_t operator()(const Reference< XInterface > & xRef) const
722
0
    {
723
0
        return reinterpret_cast<size_t>(xRef.get());
724
0
    }
725
};
726
727
}
728
729
typedef std::unordered_map
730
<
731
    Reference< XInterface >,
732
    sal_Int32,
733
    hashObjectContainer_Impl,
734
    equalObjectContainer_Impl
735
> ObjectContainer_Impl;
736
737
namespace {
738
739
class OObjectOutputStream:
740
    public ImplInheritanceHelper<
741
            ODataOutputStream, /* parent */
742
            XObjectOutputStream, XMarkableStream >
743
{
744
public:
745
    OObjectOutputStream()
746
0
        : m_nMaxId(0) ,
747
0
          m_bValidMarkable(false)
748
0
        {
749
0
        }
750
751
public:
752
    // XOutputStream
753
    virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData) override
754
0
        { ODataOutputStream::writeBytes( aData ); }
755
756
    virtual void SAL_CALL flush() override
757
0
        { ODataOutputStream::flush(); }
758
759
    virtual void SAL_CALL closeOutput() override
760
0
        { ODataOutputStream::closeOutput(); }
761
762
public:
763
    // XDataOutputStream
764
    virtual void SAL_CALL writeBoolean(sal_Bool Value) override
765
0
                { ODataOutputStream::writeBoolean( Value ); }
766
    virtual void SAL_CALL writeByte(sal_Int8 Value) override
767
0
                { ODataOutputStream::writeByte( Value ); }
768
    virtual void SAL_CALL writeChar(sal_Unicode Value) override
769
0
                { ODataOutputStream::writeChar( Value ); }
770
    virtual void SAL_CALL writeShort(sal_Int16 Value) override
771
0
                { ODataOutputStream::writeShort( Value ); }
772
    virtual void SAL_CALL writeLong(sal_Int32 Value) override
773
0
                { ODataOutputStream::writeLong( Value ); }
774
    virtual void SAL_CALL writeHyper(sal_Int64 Value) override
775
0
                { ODataOutputStream::writeHyper( Value ); }
776
    virtual void SAL_CALL writeFloat(float Value) override
777
0
                { ODataOutputStream::writeFloat( Value ); }
778
    virtual void SAL_CALL writeDouble(double Value) override
779
0
                { ODataOutputStream::writeDouble( Value ); }
780
    virtual void SAL_CALL writeUTF(const OUString& Value) override
781
0
                { ODataOutputStream::writeUTF( Value );}
782
783
    // XObjectOutputStream
784
        virtual void SAL_CALL writeObject( const Reference< XPersistObject > & r ) override;
785
786
public: // XMarkableStream
787
    virtual sal_Int32 SAL_CALL createMark() override;
788
    virtual void SAL_CALL deleteMark(sal_Int32 Mark) override;
789
    virtual void SAL_CALL jumpToMark(sal_Int32 nMark) override;
790
    virtual void SAL_CALL jumpToFurthest() override;
791
    virtual sal_Int32 SAL_CALL offsetToMark(sal_Int32 nMark) override;
792
793
public: // XServiceInfo
794
    OUString                   SAL_CALL   getImplementationName() override;
795
    Sequence< OUString >       SAL_CALL   getSupportedServiceNames() override;
796
    sal_Bool                   SAL_CALL   supportsService(const OUString& ServiceName) override;
797
798
private:
799
    void connectToMarkable();
800
private:
801
    ObjectContainer_Impl                m_mapObject;
802
    sal_Int32                           m_nMaxId;
803
    Reference< XMarkableStream >        m_rMarkable;
804
    bool                            m_bValidMarkable;
805
};
806
807
}
808
809
void OObjectOutputStream::writeObject( const Reference< XPersistObject > & xPObj )
810
0
{
811
812
0
    connectToMarkable();
813
0
    bool bWriteObj = false;
814
    // create Mark to write length of info
815
0
    sal_uInt32 nInfoLenMark = m_rMarkable->createMark();
816
817
    // length of the info data (is later rewritten)
818
0
    OObjectOutputStream::writeShort( 0 );
819
820
    // write the object identifier
821
0
    if( xPObj.is() )
822
0
    {
823
0
        Reference< XInterface > rX( xPObj , UNO_QUERY );
824
825
0
        ObjectContainer_Impl::const_iterator aIt
826
0
            = m_mapObject.find( rX );
827
0
        if( aIt == m_mapObject.end() )
828
0
        {
829
            // insert new object in hash table
830
0
            m_mapObject[ rX ] = ++m_nMaxId;
831
0
            ODataOutputStream::writeLong( m_nMaxId );
832
0
            ODataOutputStream::writeUTF( xPObj->getServiceName() );
833
0
            bWriteObj = true;
834
0
        }
835
0
        else
836
0
        {
837
0
            ODataOutputStream::writeLong( (*aIt).second );
838
0
            ODataOutputStream::writeUTF( OUString() );
839
0
        }
840
0
    }
841
0
    else
842
0
    {
843
0
        ODataOutputStream::writeLong( 0 );
844
0
        ODataOutputStream::writeUTF( OUString() );
845
0
    }
846
847
0
    sal_uInt32 nObjLenMark = m_rMarkable->createMark();
848
0
    ODataOutputStream::writeLong( 0 );
849
850
0
    sal_Int32 nInfoLen = m_rMarkable->offsetToMark( nInfoLenMark );
851
0
    m_rMarkable->jumpToMark( nInfoLenMark );
852
    // write length of the info data
853
0
    ODataOutputStream::writeShort( static_cast<sal_Int16>(nInfoLen) );
854
    // jump to the end of the stream
855
0
    m_rMarkable->jumpToFurthest();
856
857
0
    if( bWriteObj )
858
0
        xPObj->write( Reference< XObjectOutputStream > (
859
0
            static_cast< XObjectOutputStream *  >(this) ) );
860
861
0
    sal_Int32 nObjLen = m_rMarkable->offsetToMark( nObjLenMark ) -4;
862
0
    m_rMarkable->jumpToMark( nObjLenMark );
863
    // write length of the info data
864
0
    ODataOutputStream::writeLong( nObjLen );
865
    // jump to the end of the stream
866
0
    m_rMarkable->jumpToFurthest();
867
868
0
    m_rMarkable->deleteMark( nObjLenMark );
869
0
    m_rMarkable->deleteMark( nInfoLenMark );
870
0
}
871
872
873
void OObjectOutputStream::connectToMarkable()
874
0
{
875
0
    if(  m_bValidMarkable )
876
0
        return;
877
878
0
    if( ! m_bValidStream )
879
0
        throw NotConnectedException();
880
881
    // find the markable stream !
882
0
    Reference< XInterface > rTry(m_output);
883
0
    while( true ) {
884
0
        if( ! rTry.is() )
885
0
        {
886
0
            throw NotConnectedException();
887
0
        }
888
0
        Reference < XMarkableStream > markable( rTry , UNO_QUERY );
889
0
        if( markable.is() )
890
0
        {
891
0
            m_rMarkable = std::move(markable);
892
0
            break;
893
0
        }
894
0
        Reference < XActiveDataSource > source( rTry , UNO_QUERY );
895
0
        rTry = source;
896
0
    }
897
0
    m_bValidMarkable = true;
898
0
}
899
900
901
sal_Int32 OObjectOutputStream::createMark()
902
0
{
903
0
    connectToMarkable();    // throws an exception, if a markable is not connected !
904
905
0
    return m_rMarkable->createMark();
906
0
}
907
908
void OObjectOutputStream::deleteMark(sal_Int32 Mark)
909
0
{
910
0
    if( ! m_bValidMarkable )
911
0
    {
912
0
        throw NotConnectedException();
913
0
    }
914
0
    m_rMarkable->deleteMark( Mark );
915
0
}
916
917
void OObjectOutputStream::jumpToMark(sal_Int32 nMark)
918
0
{
919
0
    if( ! m_bValidMarkable )
920
0
    {
921
0
        throw NotConnectedException();
922
0
    }
923
0
    m_rMarkable->jumpToMark( nMark );
924
0
}
925
926
927
void OObjectOutputStream::jumpToFurthest()
928
0
{
929
0
    connectToMarkable();
930
0
    m_rMarkable->jumpToFurthest();
931
0
}
932
933
sal_Int32 OObjectOutputStream::offsetToMark(sal_Int32 nMark)
934
0
{
935
0
    if( ! m_bValidMarkable )
936
0
    {
937
0
        throw NotConnectedException();
938
0
    }
939
0
    return m_rMarkable->offsetToMark( nMark );
940
0
}
941
942
// XServiceInfo
943
OUString OObjectOutputStream::getImplementationName()
944
0
{
945
0
    return u"com.sun.star.comp.io.stm.ObjectOutputStream"_ustr;
946
0
}
947
948
// XServiceInfo
949
sal_Bool OObjectOutputStream::supportsService(const OUString& ServiceName)
950
0
{
951
0
    return cppu::supportsService(this, ServiceName);
952
0
}
953
954
// XServiceInfo
955
Sequence< OUString > OObjectOutputStream::getSupportedServiceNames()
956
0
{
957
0
    return { u"com.sun.star.io.ObjectOutputStream"_ustr };
958
0
}
959
960
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
961
io_OObjectOutputStream_get_implementation(
962
    css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
963
0
{
964
0
    return cppu::acquire(new OObjectOutputStream());
965
0
}
966
967
namespace {
968
969
class OObjectInputStream:
970
    public ImplInheritanceHelper<
971
        ODataInputStream, /* parent */
972
        XObjectInputStream, XMarkableStream >
973
{
974
public:
975
    explicit OObjectInputStream( const Reference < XComponentContext > &r)
976
0
        : m_rSMgr( r->getServiceManager() )
977
0
        , m_rCxt( r )
978
0
        , m_bValidMarkable(false)
979
0
        {
980
0
        }
981
982
public: // XInputStream
983
    virtual sal_Int32 SAL_CALL readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) override
984
0
        { return ODataInputStream::readBytes( aData , nBytesToRead ); }
985
986
    virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) override
987
0
        { return ODataInputStream::readSomeBytes( aData, nMaxBytesToRead ); }
988
989
    virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) override
990
0
        { ODataInputStream::skipBytes( nBytesToSkip ); }
991
992
    virtual sal_Int32 SAL_CALL available() override
993
0
        { return ODataInputStream::available(); }
994
995
    virtual void SAL_CALL closeInput() override
996
0
        { ODataInputStream::closeInput(); }
997
998
public: // XDataInputStream
999
    virtual sal_Int8 SAL_CALL readBoolean() override
1000
0
                { return ODataInputStream::readBoolean(); }
1001
    virtual sal_Int8 SAL_CALL readByte() override
1002
0
                { return ODataInputStream::readByte(); }
1003
    virtual sal_Unicode SAL_CALL readChar() override
1004
0
                { return ODataInputStream::readChar(); }
1005
    virtual sal_Int16 SAL_CALL readShort() override
1006
0
                { return ODataInputStream::readShort(); }
1007
    virtual sal_Int32 SAL_CALL readLong() override
1008
0
                { return ODataInputStream::readLong(); }
1009
    virtual sal_Int64 SAL_CALL readHyper() override
1010
0
                { return ODataInputStream::readHyper(); }
1011
    virtual float SAL_CALL readFloat() override
1012
0
                { return ODataInputStream::readFloat(); }
1013
    virtual double SAL_CALL readDouble() override
1014
0
        { return ODataInputStream::readDouble(); }
1015
    virtual OUString SAL_CALL readUTF() override
1016
0
                { return ODataInputStream::readUTF(); }
1017
1018
public: // XObjectInputStream
1019
        virtual Reference< XPersistObject > SAL_CALL readObject( ) override;
1020
1021
public: // XMarkableStream
1022
    virtual sal_Int32 SAL_CALL createMark() override;
1023
    virtual void SAL_CALL deleteMark(sal_Int32 Mark) override;
1024
    virtual void SAL_CALL jumpToMark(sal_Int32 nMark) override;
1025
    virtual void SAL_CALL jumpToFurthest() override;
1026
    virtual sal_Int32 SAL_CALL offsetToMark(sal_Int32 nMark) override;
1027
1028
public: // XServiceInfo
1029
    OUString                     SAL_CALL getImplementationName() override;
1030
    Sequence< OUString >         SAL_CALL getSupportedServiceNames() override;
1031
    sal_Bool                     SAL_CALL supportsService(const OUString& ServiceName) override;
1032
1033
private:
1034
    void connectToMarkable();
1035
private:
1036
    Reference < XMultiComponentFactory > m_rSMgr;
1037
    Reference < XComponentContext >     m_rCxt;
1038
    bool                m_bValidMarkable;
1039
    Reference < XMarkableStream > m_rMarkable;
1040
    std::vector < Reference<  XPersistObject > > m_aPersistVector;
1041
1042
};
1043
1044
}
1045
1046
Reference< XPersistObject >  OObjectInputStream::readObject()
1047
0
{
1048
    // check if chain contains a XMarkableStream
1049
0
    connectToMarkable();
1050
1051
0
    Reference< XPersistObject > xLoadedObj;
1052
1053
    // create Mark to skip newer versions
1054
0
    sal_uInt32 nMark = m_rMarkable->createMark();
1055
    // length of the data
1056
0
    sal_Int32 nLen = static_cast<sal_uInt16>(ODataInputStream::readShort());
1057
0
    if( nLen < 0xc )
1058
0
    {
1059
0
        throw WrongFormatException();
1060
0
    }
1061
1062
    // read the object identifier
1063
0
    sal_uInt32 nId = readLong();
1064
1065
    // the name of the persist model
1066
    // MM ???
1067
0
    OUString aName = readUTF();
1068
1069
    // Read the length of the object
1070
0
    sal_Int32 nObjLen = readLong();
1071
0
    if( 0 == nId && 0 != nObjLen )
1072
0
    {
1073
0
        throw WrongFormatException();
1074
0
    }
1075
1076
    // skip data of new version
1077
0
    skipBytes( nLen - m_rMarkable->offsetToMark( nMark ) );
1078
1079
0
    bool bLoadSuccessful = true;
1080
0
    if( nId )
1081
0
    {
1082
0
        if( !aName.isEmpty() )
1083
0
        {
1084
            // load the object
1085
0
            Reference< XInterface > x = m_rSMgr->createInstanceWithContext( aName, m_rCxt );
1086
0
            xLoadedObj.set( x, UNO_QUERY );
1087
0
            if( xLoadedObj.is() )
1088
0
            {
1089
0
                sal_uInt32 nSize = m_aPersistVector.size();
1090
0
                if( nSize <= nId )
1091
0
                {
1092
                    // grow to the right size
1093
0
                    Reference< XPersistObject > xEmpty;
1094
0
                    m_aPersistVector.insert( m_aPersistVector.end(), nId - nSize + 1, xEmpty );
1095
0
                }
1096
1097
0
                m_aPersistVector[nId] = xLoadedObj;
1098
0
                xLoadedObj->read( Reference< XObjectInputStream >(
1099
0
                    static_cast< XObjectInputStream * >(this) ) );
1100
0
            }
1101
0
            else
1102
0
            {
1103
                // no service with this name could be instantiated
1104
0
                bLoadSuccessful = false;
1105
0
            }
1106
0
        }
1107
0
        else {
1108
0
            if (nId >= m_aPersistVector.size())
1109
0
            {
1110
                // id unknown, load failure !
1111
0
                bLoadSuccessful = false;
1112
0
            }
1113
0
            else
1114
0
            {
1115
                // Object has already been read,
1116
0
                xLoadedObj = m_aPersistVector[nId];
1117
0
            }
1118
0
        }
1119
0
    }
1120
1121
    // skip to the position behind the object
1122
0
    skipBytes( nObjLen + nLen - m_rMarkable->offsetToMark( nMark ) );
1123
0
    m_rMarkable->deleteMark( nMark );
1124
1125
0
    if( ! bLoadSuccessful )
1126
0
    {
1127
0
        throw WrongFormatException();
1128
0
    }
1129
0
    return xLoadedObj;
1130
0
}
1131
1132
1133
void OObjectInputStream::connectToMarkable()
1134
0
{
1135
0
    if(  m_bValidMarkable )        return;
1136
1137
0
    if( ! m_bValidStream )
1138
0
    {
1139
0
        throw NotConnectedException( );
1140
0
    }
1141
1142
    // find the markable stream !
1143
0
    Reference< XInterface > rTry(m_input);
1144
0
    while( true ) {
1145
0
        if( ! rTry.is() )
1146
0
        {
1147
0
            throw NotConnectedException( );
1148
0
        }
1149
0
        Reference<  XMarkableStream > markable( rTry , UNO_QUERY );
1150
0
        if( markable.is() )
1151
0
        {
1152
0
            m_rMarkable = std::move(markable);
1153
0
            break;
1154
0
        }
1155
0
        Reference < XActiveDataSink > sink( rTry , UNO_QUERY );
1156
0
        rTry = sink;
1157
0
    }
1158
0
    m_bValidMarkable = true;
1159
0
}
1160
1161
sal_Int32 OObjectInputStream::createMark()
1162
0
{
1163
0
    connectToMarkable();    // throws an exception, if a markable is not connected !
1164
1165
0
    return m_rMarkable->createMark();
1166
0
}
1167
1168
void OObjectInputStream::deleteMark(sal_Int32 Mark)
1169
0
{
1170
0
    if( ! m_bValidMarkable )
1171
0
    {
1172
0
        throw NotConnectedException();
1173
0
    }
1174
0
    m_rMarkable->deleteMark( Mark );
1175
0
}
1176
1177
void OObjectInputStream::jumpToMark(sal_Int32 nMark)
1178
0
{
1179
0
    if( ! m_bValidMarkable )
1180
0
    {
1181
0
        throw NotConnectedException();
1182
0
    }
1183
0
    m_rMarkable->jumpToMark( nMark );
1184
0
}
1185
void OObjectInputStream::jumpToFurthest()
1186
0
{
1187
0
    connectToMarkable();
1188
0
    m_rMarkable->jumpToFurthest();
1189
0
}
1190
1191
sal_Int32 OObjectInputStream::offsetToMark(sal_Int32 nMark)
1192
0
{
1193
0
    if( ! m_bValidMarkable )
1194
0
    {
1195
0
        throw NotConnectedException();
1196
0
    }
1197
0
    return m_rMarkable->offsetToMark( nMark );
1198
0
}
1199
1200
// XServiceInfo
1201
OUString OObjectInputStream::getImplementationName()
1202
0
{
1203
0
    return u"com.sun.star.comp.io.stm.ObjectInputStream"_ustr;
1204
0
}
1205
1206
// XServiceInfo
1207
sal_Bool OObjectInputStream::supportsService(const OUString& ServiceName)
1208
0
{
1209
0
    return cppu::supportsService(this, ServiceName);
1210
0
}
1211
1212
// XServiceInfo
1213
Sequence< OUString > OObjectInputStream::getSupportedServiceNames()
1214
0
{
1215
0
    return { u"com.sun.star.io.ObjectInputStream"_ustr };
1216
0
}
1217
1218
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1219
io_OObjectInputStream_get_implementation(
1220
    css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
1221
0
{
1222
0
    return cppu::acquire(new OObjectInputStream(context));
1223
0
}
1224
1225
}
1226
1227
1228
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */